概念:线程副本
1,为共享变量在每一个线程中创建一个副本,每个线程可以访问自己内部的副本变量
2,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本
使用案例:
package com.atguigu.seven;
/**
* 需求:给一个默认为0的值 使用多个线程 +5 的操作
* t1----5
* t2----5
* t3----5
* @author Administrator
*
*/
public class ThreadLocalTest {
private static Integer num = 0;
private static ThreadLocal<Integer> threa_num = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
public static void main(String[] args) {
/*
* for (int i = 1; i <= 5; i++) { new Thread(()->{ num+=5;
* System.out.println(Thread.currentThread().getName()+"--------"+num);
* },"线程"+String.valueOf(i)).start(); }
*/
for (int i = 1; i <= 10; i++) {
new Thread(()->{
int x = threa_num.get().intValue();
x+=5;
threa_num.set(x);
System.out.println(Thread.currentThread().getName()+"--------"+threa_num.get());
},"线程"+String.valueOf(i)).start();
}
}
}
分析:
1,线程隔离
2,副本数据如何存储
常见方法
总结:
ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本
volatile 与 ThreadLocal 区别
volatile主要是用来在多线程中同步变量volatile只能确保操作的是同一块内存,并不能保证操作的原子性。所以volatile一般用于声明简单类型变量,使得这些变量具有原子性,即一些简单的赋值与返回操作将被确保不中断。但是当该变量的值由自身的上一个决定时,volatile的作用就将失效,这是由volatile关键字的性质所决定的。
所以在volatile时一定要谨慎,千万不要以为用volatile修饰后该变量的所有操作都是原子操作,不再需要synchronized关键字了
ThreadLocal和本地线程没有关系,更不是一个特殊的Thread,它只是一个线程的局部变量(其实就是一个Map),ThreadLocal会为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。