Some understanding of ThreadLocal

ThreadLocal is often asked during the interview, the paper mainly talk about some of the understanding of ThreadLocal from the following three aspects:

  • ThreadLocal used in any place
  • ThreadLocal details
  • Best Practices of ThreadLocal

ThreadLocal used in any place?

Under discussion ThreadLocal used before somewhere, let's clear, if only there is only one thread, then do not talk about ThreadLocal, ThreadLocal is in multithreaded scenarios

Use ThreadLocal induction down to the class 2:

  • Save the thread context information can be obtained at any desired place
  • Thread-safe, avoid certain situations need to consider the performance loss caused by thread safety must be synchronized

Save the thread context information can be obtained at any desired place

Due to the nature of ThreadLocal, the same thread is set in a place, at any subsequent places you can get to. It can be used to save the thread context information.

How common such as a string of subsequent associate each request, may be performed with ThreadLocal set, need to log recording method in which subsequent to the acquisition request get arbitrarily id, string together such that the entire request.

For example, there are Spring's transaction management, with ThreadLocal storage Connection, so that each can get the same DAO Connection, transaction rollback can be submitted and other operations.

hreadLocal this useful, are often used in some excellent inside the framework, we generally had little contact, but the following scenario we touch some more!

Thread-safe, avoid certain situations need to consider the performance loss caused by thread safety must be synchronized

ThreadLocal provides a new way to solve the problem of concurrent multi-threaded programs. ThreadLocal but there are limitations, let's look at Ali specification:

Each thread to read and write data in ThreadLocal thread is isolated, will not affect each other, so ThreadLocal shared object can not be resolved

Update problems!

Since no sharing of information, there is no natural competition problem, thus ensuring the performance loss in some cases the security thread, and avoid some of the cases to consider thread safety must be synchronized to bring

Such scenes Ali specification which also mentioned:

ThreadLocal details

ThreaLocal example code:

public class ThreadLocalTest {
    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {

        new Thread(() -> {
            try {
                for (int i = 0; i < 100; i++) {
                    threadLocal.set(i);
                    System.out.println(Thread.currentThread().getName() + "====" + threadLocal.get());
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } finally {
                threadLocal.remove();
            }
        }, "threadLocal1").start();


        new Thread(() -> {
            try {
                for (int i = 0; i < 100; i++) {
                    System.out.println(Thread.currentThread().getName() + "====" + threadLocal.get());
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } finally {
                threadLocal.remove();
            }
        }, "threadLocal2").start();
    }
}

Code running results:

从运行的结果我们可以看到threadLocal1进行set值对threadLocal2并没有任何影响!

Thread、ThreadLocalMap、ThreadLocal总览图:

Thread类有属性变量threadLocals (类型是ThreadLocal.ThreadLocalMap),也就是说每个线程有一个自己的ThreadLocalMap ,所以每个线程往这个ThreadLocal中读写隔离的,并且是互相不会影响的。

一个ThreadLocal只能存储一个Object对象,如果需要存储多个Object对象那么就需要多个ThreadLocal

如图:

看到上面的几个图,大概思路应该都清晰了,我们Entry的key指向ThreadLocal用虚线表示弱引用 ,下面我们来看看ThreadLocalMap:

java对象的引用包括 :强引用,软引用,弱引用,虚引用 。

因为这里涉及到弱引用,简单说明下:

弱引用是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,如果该对象仅仅被弱引用关联,那么就会被回收。

当仅仅只有ThreadLocalMap中的Entry的key指向ThreadLocal的时候,ThreadLocal会进行回收的

ThreadLocal被垃圾回收后,在ThreadLocalMap里对应的Entry的键值会变成null,但是Entry是强引用,那么Entry里面存储的Object,并没有办法进行回收,所以ThreadLocalMap 做了一些额外的回收工作。

ThreadLocal的最佳实践!

很多时候,我们都是用在线程池的场景,程序不停止,线程基本不会销毁

由于线程的生命周期很长,如果我们往ThreadLocal里面set了很大很大的Object对象,虽然set、get等等方法在特定的条件会调用进行额外的清理,但是ThreadLocal被垃圾收集器回收后,在ThreadLocalMap里对应的Entry的键会变成null,但是后续在也没有操作set、get等方法了。

所以最佳实践,应该在我们不使用的时候,主动调用remove方法进行清理。

这里把ThreadLocal定义为static还有一个好处就是,由于ThreadLocal有强引用在,那么在ThreadLocalMap里对应的Entry的键会永远存在,那么执行remove的时候就可以正确进行定位到并且删除!!!

最佳实践做法应该为:

抽象为:

try {
    // 其它业务逻辑
} finally {
    threadLocal对象.remove();
}

思考

如果面试的时候,可以把上面的内容都可以讲到,个人觉得就非常好了,回答的就挺完美了。但是如果你可以进行下面的回答,那么就更完美了。

对于ThreadLocal,我在看Netty源码的时候,还了解过FastThreadLocal,xxxxx列一些内容。那就是一个升级了。实际上,FastThreadLocal的吞吐量比ThreadLocal高很多。

Guess you like

Origin www.cnblogs.com/kyoner/p/11280344.html