ThreadLocal基本介绍:
- 线程并发:在多线程并发场景下
- 传递数据:我们可以通过ThreadLocal在同一线程、不同组件中传递公共变量
- 线程隔离:每个线程的变量都是独立的,不会互相影响
常用方法
方法声明 | 描述 |
---|---|
ThreadLocal() | 创建ThreadLocal对象 |
public void set(T value) | 设置 当前线程绑定的局部变量 |
public T get() | 获取 当前线程绑定的局部变量 |
public void remove() | 删除 当前线程绑定的局部变量 |
代码例子:
public class MyDemo01 {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public static void main(String[] args) {
MyDemo01 demo = new MyDemo01();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
demo.setContent(Thread.currentThread().getName() + "的数据");
System.out.println("-------------------");
System.out.println(Thread.currentThread().getName() + "--->" + demo.getContent());
}
});
thread.setName("线程" + i);
thread.start();
}
}
}
运行结果:
-------------------
-------------------
-------------------
-------------------
-------------------
线程0--->线程3的数据
线程1--->线程1的数据
线程2--->线程3的数据
线程3--->线程3的数据
线程4--->线程3的数据
使用普通的线程进行设置和获取时,可能会出现线程1访问到了线程2的数据。使用ThreadLocal即可解决:
public class MyDemo01 {
ThreadLocal<String> t1= new ThreadLocal<>();
private String content;
public String getContent() {
// return content;
return t1.get();
}
public void setContent(String content) {
t1.set(content);
// this.content = content;
}
……………………省略后续代码………………
变量被绑定到ThreadLocal对象上,每个线程拿到的值都是自己线程的,不会串。
ThreadLocal类与synchronized关键字
以上例子的另一种改法是:
public static void main(String[] args) {
MyDemo02 demo = new MyDemo02();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
synchronized (MyDemo02.class){
demo.setContent(Thread.currentThread().getName() + "的数据");
System.out.println("-------------------");
System.out.println(Thread.currentThread().getName() + "--->" + demo.getContent());
}
}
});
thread.setName("线程" + i);
thread.start();
}
}
使用synchronized
关键字锁住代码
区别:
synchronized | ThreadLocal | |
---|---|---|
原理 | 同步机制采用“以时间换空间”的方式,只提供了一份变量,让不同的线程排队访问 | Thread Local采用“以空间换时间”的方式,为每一个线程都提供了一份变量的副本,从而实现同时访问而互不干扰 |
侧重点 | 多个线程之间访问资源的同步 | 多线程中让每个线程之间的数据相互隔离 |
总结:在刚刚的案例中,虽然使用ThreadLocal和synchronized都能解决问题,但是ThreadLocal可以使程序拥有更高的并发性