概念:多线程中访问共享数据的时候会有线程间数据同步的问题,并不是所有时候都会用到共享数据,有些数据只需要在其线程内使用,数据就被封闭在各自的线程之中,就不需要同步,这种通过将数据封闭在线程中而避免使用同步的技术称为“线程封闭”。
线程封闭的具体实现:
1、ThreadLocal
2、局部变量
6.1 ThreadLocal
ThreadLocal是Java里的一种特殊的变量。
它是一个线程级别的变量,每个线程都有个ThreadLocal就是每个线程都拥有自己独立的一个变量,竞争条件被彻底消除,并发模式下是绝对安全的变量。
ThreadLocal<T> var = new ThreadLocal<T>();
会自动在每个线程上创建一个T的副本,副本之间彼此独立,互不影响。
可以用ThreadLocal存储一些参数,以便在线程中多个方法中使用,用来代替方法传参的做法。
6.1.1 ThreadLocal实例
public class ThreadLocalDemo {
/**
* threadLocal变量,每个线程都有一个副本,互不干扰
*/
public static ThreadLocal<Bread> value = new ThreadLocal<>();
public static void main(String[] args) throws Exception {
producer1Thread();
producer2Thread();
}
/**
* threadlocal测试
*
* @throws Exception
*/
public static Thread producer1Thread() throws Exception {
Thread producer1Thread = new Thread(() -> {
synchronized (value){
System.out.println("producer1Thread: " + value.get());
value.set(new Bread("producer1Bread", 10f));
System.out.println("producer1Thread: " + value.get());
}
});
producer1Thread.start();
return producer1Thread;
}
/**
* threadlocal测试
*
* @throws Exception
*/
public static Thread producer2Thread() throws Exception {
Thread producer2Thread = new Thread(() -> {
synchronized (value){
System.out.println("producer2Thread: " + value.get());
value.set(new Bread("producer2Bread", 10f));
System.out.println("producer2Thread: " + value.get());
}
});
producer2Thread.start();
return producer2Thread;
}
@Getter
@Setter
@AllArgsConstructor
@ToString
protected static class Bread {
private String name;
private float price;
}
}
运行结果:
从运行结果可以看出,两个线程间的ThreadLocal所存放的Bread是互不影响的,也就是说ThreadLocal变量是线程独立的。
6.2 局部变量
前面第1章节介绍过虚拟机栈,虚拟机栈中为每个线程分配一定的内存空间,每个线程的内存空间中有它们自己的栈帧(一个方法对应一个栈帧),栈帧中包括了局部变量表、操作数栈等信息,其它线程没法访问这个局部变量表。正因如此,局部变量也是栈封闭的一种形式。