When and how should I use a ThreadLocal variable?

2018-12-31 15:50发布

When should I use a ThreadLocal variable?

How is it used?

24条回答
还给你的自由
2楼-- · 2018-12-31 16:29

There are 3 scenarios for using a class helper like SimpleDateFormat in multithread code, which best one is use ThreadLocal

Scenarios

1- Using like share object by the help of lock or synchronization mechanism which makes the app slow

2- Using as a local object inside a method

In this scenario, if we have 4 thread each one calls a method 1000 time then we have
4000 SimpleDateFormat object created and waiting for GC to erase them

3- Using ThreadLocal

if we have 4 thread and we gave to each thread one SimpleDateFormat instance
so we have 4 threads, 4 objects of SimpleDateFormat.

There is no need of lock mechanism and object creation and destruction. (Good time complexity and space complexity)

查看更多
永恒的永恒
3楼-- · 2018-12-31 16:30

Thread-local variables are often used to prevent sharing in designs based on mutable Singletons or global variables.

It can be used in scenarios like making seperate JDBC connection for each thread when you are not using a Connection Pool.

private static ThreadLocal<Connection> connectionHolder
           = new ThreadLocal<Connection>() {
      public Connection initialValue() {
           return DriverManager.getConnection(DB_URL);
          }
     };

public static Connection getConnection() {
      return connectionHolder.get();
} 

When you call getConnection, it will return a connection associated with that thread.The same can be done with other properties like dateformat, transaction context that you don't want to share between threads.

You could have also used local variables for the same, but these resource usually take up time in creation,so you don't want to create them again and again whenever you perform some business logic with them. However, ThreadLocal values are stored in the thread object itself and as soon as the thread is garbage collected, these values are gone too.

This link explains use of ThreadLocal very well.

查看更多
梦该遗忘
4楼-- · 2018-12-31 16:31

Essentially, when you need a variable's value to depend on the current thread and it isn't convenient for you to attach the value to the thread in some other way (for example, subclassing thread).

A typical case is where some other framework has created the thread that your code is running in, e.g. a servlet container, or where it just makes more sense to use ThreadLocal because your variable is then "in its logical place" (rather than a variable hanging from a Thread subclass or in some other hash map).

On my web site, I have some further discussion and examples of when to use ThreadLocal that may also be of interest.

Some people advocate using ThreadLocal as a way to attach a "thread ID" to each thread in certain concurrent algorithms where you need a thread number (see e.g. Herlihy & Shavit). In such cases, check that you're really getting a benefit!

查看更多
牵手、夕阳
5楼-- · 2018-12-31 16:32

Webapp server may keep a thread pool, and a ThreadLocal var should be removed before response to the client, thus current thread may be reused by next request.

查看更多
看淡一切
6楼-- · 2018-12-31 16:33

In Java, if you have a datum that can vary per-thread, your choices are to pass that datum around to every method that needs (or may need) it, or to associate the datum with the thread. Passing the datum around everywhere may be workable if all your methods already need to pass around a common "context" variable.

If that's not the case, you may not want to clutter up your method signatures with an additional parameter. In a non-threaded world, you could solve the problem with the Java equivalent of a global variable. In a threaded word, the equivalent of a global variable is a thread-local variable.

查看更多
还给你的自由
7楼-- · 2018-12-31 16:34

Since Java 8 release, there is more declarative way to initialize ThreadLocal:

ThreadLocal<Cipher> local = ThreadLocal.withInitial(() -> "init value");

Until Java 8 release you had to do the following:

ThreadLocal<String> local = new ThreadLocal<String>(){
    @Override
    protected String initialValue() {
        return "init value";
    }
};

Moreover, if instantiation method (constructor, factory method) of class that is used for ThreadLocal does not take any parameters, you can simply use method references (introduced in Java 8):

class NotThreadSafe {
    // no parameters
    public NotThreadSafe(){}
}

ThreadLocal<NotThreadSafe> container = ThreadLocal.withInitial(NotThreadSafe::new);

Note: Evaluation is lazy since you are passing java.util.function.Supplier lambda that is evaluated only when ThreadLocal#get is called but value was not previously evaluated.

查看更多
登录 后发表回答