ThreadLocal 系列:
下面启动 9 个子线程,每个子线程都将名字(thread - i)存在同一个变量中,然后再打印出来。可以想到,如果同一个变量可以做到线程间隔离(互补影响),控制台正确的结果应该是 thread - 0 到 thread - 8。
下面就分别演示演示这个变量的两种实现:1.普通变量String ,2.ThreadLocal<String>
1.普通变量
public class StringTest {
// 保存线程名的普通变量value
private String value;
// 不直接设置value,而是暴露出get和set方法
private String getString() { return string; }
private void setString(String string) { this.string = string; }
public static void main(String[] args) {
StringTest test= new StringTest ();
int threads = 9; // 要启动的线程个数
CountDownLatch countDownLatch = new CountDownLatch(threads); // countDownLatch 用于防止主线程在子线程未完成前结束
// 启动9个子线程
for (int i = 0; i < threads; i++) {
Thread thread = new Thread(() -> {
test.setString(Thread.currentThread().getName()); // 向变量value中存入线程名 thread - i
System.out.println(test.getString()); // 然后打印出来。注:这里可能存在并发
countDownLatch.countDown(); // 门栓-1
}, "thread - " + i);
thread.start();
}
}
countDownLatch.await(); // 等countDownLatch为0时,主线程恢复运行
}
结果如下:
thread - 1
thread - 2
thread - 1
thread - 3
thread - 4
thread - 5
thread - 6
thread - 7
thread - 8
可以看到没有 thread - 0,反而 thread - 1 出现了两次,所以使用普通类型的变量无法实现同一变量对于不同线程隔离
2.ThreadLocal
使用ThreadLocal时,一般声明为static,原因有二:
- 一个类一个ThreadLocal --> 当前线程一个Entry 就够了
- 使用时调用方便
public class ThreadLocalStringTest {
// 保存线程名的ThreadLocal变量threadLocal
// 注:这里除了是String,也可是别的任何类型(Integer,List,Map...)
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
// 不直接操作 threadLocal,而是封装成 set/get 方法
private String getString() { return threadLocal.get(); }
private void setString(String string) { threadLocal.set(string);}
public static void main(String[] args) {
ThreadLocalStringTest test= new ThreadLocalStringTest();
int threads = 9; // 要创建的子线程个数
CountDownLatch countDownLatch = new CountDownLatch(threads); // countDownLatch 用于防止主线程在子线程未完成前结束
// 创建 9 个线程
for (int i = 0; i < threads; i++) {
Thread thread = new Thread(() -> {
test.setString(Thread.currentThread().getName()); // 向ThreadLocal中存入当前线程名 thread - i
System.out.println(test.getString()); // 向ThreadLocal获取刚存的线程名。注:可能存在并发
countDownLatch.countDown(); // 门栓-1
}, "thread - " + i);
thread.start();
}
countDownLatch.await(); // 等countDownLatch为0时,主线程恢复运行
}
}
运行结果:
thread - 0
thread - 1
thread - 2
thread - 3
thread - 4
thread - 5
thread - 6
thread - 7
thread - 8
可以看到运行结果符合预期,即ThreadLocal实现了同一变量在线程间隔离。另外ThreadLocal还可以用于单点登录,用来保存不同请求线程的token,然后在解析时取出。
本文标题:【Java并发编程】ThreadLocal(一):使用示例
本文链接:https://blog.quwenai.cn/post/10104.html
版权声明:本文不使用任何协议授权,您可以任何形式自由转载或使用。






还没有评论,来说两句吧...