4问搞定java中的ThreadLocal
Q: ThreadLocal的常见使用场景?
A:
每个线程中需要维护1个不同的副本, 但这个副本可能是某一个时刻一起塞入每个线程的, 只不过之后该副本的变化 不再受其他线程的影响。
常见场景有连接器管理模块connectorManager, 每个线程持有的connect变量是单独使用的,不会互相影响或者需要加锁。原因就是将其作为副本放入每个线程,当线程启动连接或者关闭时,不影响其他线程里的getConnect方法。
Q: ThreadLocal和Synchronized关键字的区别?
A:
Synchronized是用时间的消耗,来换取数据同步以及互不冲突
ThreadLocal则是用空间的消耗,来换取数据之间互不冲突(不涉及同步)
Q:
TheadLocal在每个线程中是以什么形式存储的? 原理是什么
A:
这篇文章讲解ThreadLocal源码讲解的蛮好的:
Java并发编程:深入剖析
看完后用我自己的话总结一下就是:
-
在某个线程中调用 某threadlocal.set(value)时, 其实就是在该线程中新建了1个threalocalMap, 然后把threadLocal作为键,value作为值,放进本线程的threalocalMap中。
-
当在线程中调用threadlocal.get()的时候,就是从线程的threadLocalMap中获取这个threadLocal对应的值
如果get不到,则可以通过自定义initValue方法生成一个threadLocal的默认值
见如下图所示:
Q: 下面这个代码会报什么错?(例子改编自上面链接的文章)
public class Test {
ThreadLocal<String> stringLocal = new ThreadLocal<String>();
public static void main(String[] args) throws InterruptedException {
final Test test = new Test();
System.out.println(test.getString());
Thread thread1 = new Thread(){
public void run() {
System.out.println(stringLocal.get());
};
};
thread1.start();
thread1.join();
stringLocal.set("thread0")
System.out.println(test.getString());
}
}
在Thread1中,会报空指针, 因为调用get之前没有做过set, 此时做get会报错。
一种方式改成这样:
Thread thread1 = new Thread(){
public void run() {
stringLocal.set("thread1")
System.out.println(stringLocal.get());
};
};
另一种是给stringLocal设置默认值,这种一般用于能直接根据线程推导出初始值的情况:
ThreadLocal<String> stringLocal = new ThreadLocal<String>(){;
protected String initialValue() {
return xxx;
};
};
正确set之后, 答案就会返回thread0和thread1, 且后续怎么set,两边都不会互相影响各自的threadLocal,虽然看起来是都用的是同一个Test里的成员。
- 点赞
- 收藏
- 关注作者
评论(0)