ThreadLocal(基于JDK1.8)

知识点1:ThreadLocal是什么?

需要理解线程安全,简单来说造成线程不安全的原因有两个。

  • 不想共享的变量被共享了

  • 想共享的没及时共享

ThreadLocal解决的是第一个问题,很多情况下我们不希望不同线程之间能互相访问操作对方的变量。例如一个web服务器,多个用户并发访问,用户A有用户A的userId,用户B有用户B的userId。这时候可以使用ThreadLocal保存每个访问线程对应的userId,各读各的,互不干扰。

权威解释

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its{@code get} or {@code set} method) has its own, independently initialized copy of the variable. {@code ThreadLocal} instances are typically private static fields in classes that wish to associate state with a thread (e.g. a user ID or Transaction ID).

Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the {@code ThreadLocal} instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

不翻译了,记几点解释说明如下:

  • ThreadLocal对象通常是private static fields

  • 线程运行结束后可以对该线程的变量副本进行回收,除非该副本有别的引用

  • 关键字:副本,线程独享

一个例子,运行两个线程分别设置userId的值,可以看到不同线程互不干扰。

 
  1. public class Test {

  2.  

  3.    private static ThreadLocal<String> userId = ThreadLocal.withInitial(() -> "init_id");

  4.  

  5.    public static void main(String[] args) throws InterruptedException {

  6.        Thread thread1 = new Thread(() -> {

  7.            try {

  8.            // 线程1两秒之后获得userid,并且设置userid为id1

  9.                TimeUnit.SECONDS.sleep(2);

  10.                System.out.println("initial userId in thread1:" + userId.get());

  11.                userId.set("id1");

  12.                System.out.println("thread1 set userId id1");

  13.            } catch (InterruptedException e) {

  14.                e.printStackTrace();

  15.            }

  16.        });

  17.  

  18.        Thread thread2 = new Thread(() -> {

  19.            try {

  20.                // 线程二获取初始的userId,然后一秒之后设置为id2,再过两秒之后再次读取userid

  21.                System.out.println("initial userId in thread2:" + userId.get());

  22.                TimeUnit.SECONDS.sleep(1);

  23.                userId.set("id2");

  24.                System.out.println("thread2 set userId id2");

  25.                TimeUnit.SECONDS.sleep(2);

  26.                System.out.println("now userId in thread2:" + userId.get());

  27.  

  28.            } catch (InterruptedException e) {

  29.                e.printStackTrace();

  30.            }

  31.        });

  32.  

  33.        thread1.start();

  34.        thread2.start();

  35.  

  36.        // 在main线程等待两个线程执行结束

  37.        thread1.join();

  38.        thread2.join();

  39.  

  40.    }

  41. }

 

 
  1. initial userId in thread2:init_id

  2. thread2 set userId id2

  3. initial userId in thread1:init_id

  4. thread1 set userId id1

  5. now userId in thread2:id2

知识点二:ThreadLocal实现原理

最关键代码如下,在任何代码中执行Thread.currentThread(),都可以获取到当前执行这段代码的Thread对象。既然获得了当前的Thread对象了,如果让我们自己实现线程独享变量怎么实现呢?自然而然就会想到在先获取当前Thread对象,然后在当前Thread对象中使用一个容器来存储这些变量,这样每个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值