当前位置: 首页 > 后端技术 > Java

4道题教你如何在java中处理ThreadLocal

时间:2023-04-01 15:00:20 Java

摘要:ThreadLocal是一种不同于锁同步的方法,保证在多线程访问时可以避免线程不安全。本文分享自华为云社区《4问搞定java中的ThreadLocal》,作者:breakDraw。多个线程访问同一个共享变量时容易出现并发问题,尤其是多个线程写入一个变量时,为了保证线程安全,一般用户在访问共享变量时需要采取额外的同步措施来保证线程安全。ThreadLocal是一种除了同步加锁的方法之外保证多线程访问中线程不安全的一种方法。当我们创建一个变量时,如果每个线程都访问它,那么访问的是线程自己的变量,这样就不会出现线程不安全的情况。Q:ThreadLocal的常见使用场景?A:每个线程都需要维护一个不同的副本,但是这个副本可能在某个时刻被塞进了每个线程,但是这个副本的改变不会再受到其他线程的影响。一个常见的场景是连接器管理模块connectorManager。每个线程持有的connect变量是独立使用的,不会互相影响,也不需要加锁。原因是将它作为一个副本放入每个线程中。当一个线程启动连接或关闭连接时,不会影响其他线程中的getConnect方法。问:ThreadLocal和Synchronized关键字有什么区别?A:Synchronized用时间消耗来换取数据同步和不冲突。ThreadLocal使用空间消耗来换取数据之间的不冲突(不涉及同步)。Q:每个线程中的TheadLocal是什么?存储?原理是什么?A:这篇文章很好的解释了ThreadLocal源码:Java并发编程:深入浅析看完之后,我可以用自己的话总结一下:当某个threadlocal.set(value)在某个线程被调用时,在fact即在本线程中新建一个threadLocalMap,然后以threadLocal为key,value为value,放入本线程的threadLocalMap中。在线程中调用threadlocal.get()时,从线程的threadLocalMap中获取这个threadLocal对应的值。如果获取不到,可以通过自定义initValue方法生成一个默认值threadLocal,如下图:Q:下面的代码会报什么错?(示例改编自上面链接的文章)publicclassTest{ThreadLocalstringLocal=newThreadLocal();publicstaticvoidmain(String[]args)throwsInterruptedException{finalTesttest=newTest();系统.out.println(test.getString());线程thread1=newThread(){publicvoidrun(){System.out.println(stringLocal.get());};};thread1.start();线程1.join();stringLocal.set("thread0")System.out.println(test.getString());}}在Thread1中,会报空指针,因为在调用get之前没有set过,此时get已经完成了,会报错。将它更改为这样的一种方法:Threadthread1=newThread(){publicvoidrun(){stringLocal.set("thread1")System.out.println(stringLocal.get());};};另一种是设置stringLocal的默认值,一般用于初始值可以直接从线程导出的情况:ThreadLocalstringLocal=newThreadLocal(){;protectedStringinitialValue(){returnxxx;};};正确设置后,答案会返回thread0和thread1,以后怎么设置,双方不会影响对方的threadLocal,虽然看起来都是在同一个Test中使用成员。点击关注,第一时间了解华为云的新鲜技术~