ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java Thread Local – How to use and code sample(转)

2019-11-13 09:01:50  阅读:201  来源: 互联网

标签:use code Java thread Thread local set Local public


转载自:https://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/

Thread Local is an interesting and useful concept, yet most of the Java developers are not aware of how to use that. In this post, I’ll explain what is Thread Local and when to use it, with an example code.

Since it’ll be little tough to understand this concept at first, I’ll keep the explanation as simple as possible (corollary: you shouldn’t use this code as it is in a production environment. Grasp the concept and modify upon it!)

Let’s begin.

What is Thread Local?

Thread Local can be considered as a scope of access, like a request scope or session scope. It’s a thread scope. You can set any object in Thread Local and this object will be global and local to the specific thread which is accessing this object. Global and local!!? Let me explain:

  • Values stored in Thread Local are global to the thread, meaning that they can be accessed from anywhere inside that thread. If a thread calls methods from several classes, then all the methods can see the Thread Local variable set by other methods (because they are executing in the same thread). The value need not be passed explicitly. It’s like how you use global variables.
  • Values stored in Thread Local are local to the thread, meaning that each thread will have its own Thread Local variable. One thread can not access/modify other thread’s Thread Local variables.

Well, that’s the concept of Thread Local. I hope you understood it (if not, please leave a comment).

 

When to use Thread Local?

We saw what is thread local in the above section. Now let’s talk about the use cases. i.e. when you’ll be needing something like Thread Local.

I can point out one use case where I used thread local. Consider you have a Servlet which calls some business methods. You have a requirement to generate a unique transaction id for each and every request this servlet process and you need to pass this transaction id to the business methods, for logging purpose. One solution would be passing this transaction id as a parameter to all the business methods. But this is not a good solution as the code is redundant and unnecessary.

To solve that, you can use Thread Local. You can generate a transaction id (either in servlet or better in a filter) and set it in the Thread Local. After this, what ever the business method, that this servlet calls, can access the transaction id from the thread local.

This servlet might be servicing more that one request at a time. Since each request is processed in separate thread, the transaction id will be unique to each thread (local) and will be accessible from all over the thread’s execution (global).

Got it!?

How to use Thread Local?

Java provides a ThreadLocal object using which you can set/get thread scoped variables. Below is a code example demonstrating what I’d explained above.

Lets first have the Context.java file which will hold the transactionId field.

package com.veerasundar;

public class Context {

    private String transactionId = null;

        /* getters and setters here */

}

Now create the MyThreadLocal.java file which will act as a container to hold our context object.

package com.veerasundar;

/**
 * this class acts as a container to our thread local variables.
 * @author vsundar
 *
 */
public class MyThreadLocal {

    public static final ThreadLocal userThreadLocal = new ThreadLocal();

    public static void set(Context user) {
        userThreadLocal.set(user);
    }

    public static void unset() {
        userThreadLocal.remove();
    }

    public static Context get() {
        return userThreadLocal.get();
    }
}

In the above code, you are creating a ThreadLocal object as a static field which can be used by rest of the code to set/get thread local variables.

Let’s create our main class file which will generate and set the transaction ID in thread local and then call the business method.

package com.veerasundar;

public class ThreadLocalDemo extends Thread {

    public static void main(String args[]) {

        Thread threadOne = new ThreadLocalDemo();
        threadOne.start();

        Thread threadTwo = new ThreadLocalDemo();
        threadTwo.start();
    }

    @Override
    public void run() {
        // sample code to simulate transaction id
        Context context = new Context();
        context.setTransactionId(getName());

        // set the context object in thread local to access it somewhere else
        MyThreadLocal.set(context);

        /* note that we are not explicitly passing the transaction id */
        new BusinessService().businessMethod();
        MyThreadLocal.unset();

    }
}

Finally, here’s the code for the BusinessService.java which will read from thread local and use the value.

package com.veerasundar;

public class BusinessService {

    public void businessMethod() {
        // get the context from thread local
        Context context = MyThreadLocal.get();
        System.out.println(context.getTransactionId());
    }
}
Thread-0
Thread-1

As you might see, even though we are not explicitly passing the transaction id, the value can be accessed from the business method and printed on the console. Adding to it, the transaction ID differs for each thread (0 and 1).

Well, that’s it. I hope I’d explained it in a simple possible way. Please let me know what do you think about this article in comments. Do leave a comment if you want to add anything to this topic.

 

问:Very nice article. Thanks for sharing.
One question, userThreadLocal of MyThreadLocal class is declared as public static final.
That mean, only one userThreadLocal is created.
So why Thread-0 is not over-written by Thread-1?

答:

Think of "ThreadLocal<t>" as "Map<thread, t="">" conceptually.

If a thread invokes userThreadLocal.get(), it's equivalent to think as map.get(Thread.currentThread().getId())

Now whenever a thread invokes userThreadLocal for the first time, the `initialValue()` of the `ThreadLocal` class gets called. A thread can set the value of (as if it were a thread's own copy) userThreadLocal by userThreadLocal.set() method. And now when the thread calls userThreadLocal.get(), the newly set value is returned.

问: I might have confused the concepts: Taking the example of a unique transaction id for business...Why just not generate the uuid using a random number a generator and pass this uuid to the business method in a regular variable?

答:Because you might not be accessing the id in a function being called directly. You might need to go through several layers of function calls before getting to the business logic - this makes it tedious to change all those functions. Using the ThreadLocal storage makes is convenient, but it should be used with caution.

 

标签:use,code,Java,thread,Thread,local,set,Local,public
来源: https://www.cnblogs.com/passedbylove/p/11846658.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有