ThreadLocal:线程本地变量.
在java的java.lang.Thread类中有个threadLocals变量,该变量的类型是ThreadLocal的内部类ThreadLocalMap,该变量是一个map,保存着该线程的独有的变量副本,所有通过ThreadLocal维护的变量都是存放在当前线程的这个threadLocals的Map中所以这些变量都是线程安全的,下面是Thread类中的该变量定义:
1 | /* ThreadLocal values pertaining to this thread. This map is maintained |
简单来说ThreadLocal作为解决并发问题的另一种思路是:用“以空间换取时间”的方式来代替“以时间换取空间”的sychronized方式。每一个线程都有自己独有的ThreadLocalMap变量表,也就不存在线程安全问题了,值得注意的是,不要错误的理解为ThreadLocal是用来解决共享变量和协调线程同步的方案,它是为了方便每个线程处理自己的状态而引入的一个机制。
下面看看java中ThreadLocal怎么使用:
ThreadLocal
下面通过一个列子来说明ThreadLocal怎么使用:
先创建一个任务:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class Task {
ThreadLocal<Integer> value = new ThreadLocal<Integer>(){
protected Integer initialValue() {
return 1;
}
};
public Integer add(){
value.set(value.get()+1);
return value.get();
}
public String toString() {
return value.get().toString();
}
}
该任务实现每个线程计数,通过ThreadLocal的方式管理计数器,通过覆盖initialValue方法的方式,给该计数器赋初始值为1,然后在add的时候先从本地变量中拿出计数器的值,然后再加1,然后再set回去,add方法有三个步骤,即:取值,+1,写入,但是可以看到我们没有对该方法加任何的锁操作,但是它依然是线程安全的,因为每个线程都会有一份独立的本地变量,也就是每个线程都有一个计数器,它们互相不影响。接下来创建一个可运行任务,实现Runnable接口:
1 | public class ThreadLocalTask implements Runnable { |
该对象持有一个Task对象,然后让task调用add方法十次并打印,创建该类的目的是为了让所有的ThreadLocalTask对象都持有同一个Task对象,以验证不同的线程对于该Task对象有不同本地线程变量。接下来创建一个测试类:
1 | public class ThreadLocalTest { |
通过创建一个线程池让五个ThreadLocalTask任务同时运行,结果:
1 | pool-1-thread-1--1 |
从结果可以看出每个线程都是从1开始到10结束,均互不干扰的执行了10次加运算。
以上就是ThreadLocal的简单使用,接下来分析一下在jdk8中ThreadLocal的实现原理:java并发(3)ThreadLocal的使用及实现原理(实现原理)