ThreadLocal实现原理和使用场景

2023-07-29,,

ThreadLocal是线程本地变量,每个线程中都存在副本。

实现原理

每个线程中都有一个ThreadLocalMap,而ThreadLocalMap中的key即是ThreadLocal。

 内存泄漏:

ThreadLocal变量存储在栈内存中,对应对象存储在堆内存中,这个指向是强引用关系。

同样,ThreadLocalMap变量存储在栈内存中,对应对象key-value存储在堆内存中,也是强引用关系。同时map中的key也指向了threadlocal。

如果ThreadLocal变量被置为空,但是map仍存在引用,会导致堆中的对象无法释放,java已将map中的key优化为弱引用(WeakReference)。

但是value本身也存在强引用的关系,value并不会被释放,所以依然存在内存泄漏问题。

解决方法是,手动调用threadlocal的remove方法。

使用:

 1 public class Main {
2 private static ThreadLocal<Integer> tl = new ThreadLocal<>();
3 public static void main(String[] args) throws InterruptedException{
4 CountDownLatch c = new CountDownLatch(1);
5 ThreadPoolExecutor tpe = new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS,
6 new ArrayBlockingQueue<>(3));
7 tpe.execute(new Runnable() {
8 @Override
9 public void run() {
10 System.out.println(Thread.currentThread().getName());
11 System.out.println(tl.get());
12 tl.set(1);
13 System.out.println(tl.get());
14 tl.remove();
15 c.countDown();
16 }
17 });
18 tpe.execute(new Runnable() {//模拟
19 @Override
20 public void run() {
21 try{c.await();}catch (InterruptedException e){};//让第一个线程先执行
22 System.out.println(Thread.currentThread().getName());
23 System.out.println(tl.get());
24 tl.set(2);
25 System.out.println(tl.get());
26 tl.remove();
27 }
28 });
29 tpe.shutdown();
30 }
31 }

应用场景

1,Spring多数据源配置的切换;

2,Spring事务注解的实现;

3,日志框架slf4j中的MDC类的实现

待更多补充。

ThreadLocal实现原理和使用场景的相关教程结束。

《ThreadLocal实现原理和使用场景.doc》

下载本文的Word格式文档,以方便收藏与打印。