ThreadLocal作用:
通常我们创建的变量可以被任一个线程访问并修改,如果想实现每一个线程都有自己专属本地变量时,该变量不受其他线程影响,此时可以使用ThreadLocal。
-
ThreadLocal有三个常用方法,set()、get()、remove()。
ThreadLocal<Integer> local = new ThreadLocal<>();
-
调用local.set()方法,对当前线程进行赋值。事实上set的值保存在当前线程的ThreadLocalMap中,而不是ThreadLocal中,ThreadLocal可以看作仅对ThreadLocalMap进行了封装,只传递参数,ThreadLocalMap可以看作是为ThreadLocal定制的HashMap。存放时,key就是ThreadLocal对象即这里定义的local,我们添加的变量Integer值作为value来存放。每个线程都有自己的ThreadLocalMap。
-
当我们在同一个线程中定义了第二个或多个ThreadLocal时,
ThreadLocal<Integer> local2 = new ThreadLocal<>();
接着通过local2.set()进行赋值时,值还会保存到仅有的一个ThreadLocalMap中,而不会再创建一个ThreadLocalMap。源码中是这样,两个ThreadLocal属于同一线程,就直接往map中添加元素,所以只存在一个ThreadLocalMap:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
- local.get()、local2.get()分别获取到的是当前线程中我们存放的Integer变量值。
示例1:
使用线程池(顺便学一下线程池的使用哈哈)创建10个线程来存放Integer值 1-10。
public class ThreadLocalTest {
public static void main(String[] args) throws InterruptedException{
ThreadLocal<Integer> local = new ThreadLocal<>();
//创建一个线程池,初始化10个线程,最多15个线程,60SECONDS,多出的线程经过60s没活就回收,
// 保持10个线程,new LinkedBlockingQueue() 用来放任务的集合
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10,15,
60, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
for (int i = 0; i < 10; i++) {
int I = i + 1;
//执行一次为一个线程,执行十次共10个线程
threadPool.execute(new Runnable() {
@Override
public void run() {
local.set(I);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 的Integer值为:"+ local.get() );
}
});
}
threadPool.shutdown();
}
}
实例2:
public class Person {
private int age;
private String name;
public Person(final int age, final String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(final int age) {
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(final String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
public class ThreadLocalTest1 {
public static void main(String[] args) {
ThreadLocal<Person> local = new ThreadLocal<>();
Person p1 = new Person(23,"张三");
Person p2 = new Person(45,"李四");
Person p3 = new Person(76,"王五");
Person p4 = new Person(98,"赵六");
ArrayList<Person> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
//创建一个线程池,初始化10个线程,最多15个线程,60SECONDS,多出的线程经过60s没活就回收,
// 保持10个线程,new LinkedBlockingQueue() 用来放任务的集合
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10,15,
60, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
for (int i = 0; i < 4; i++) {
Person p = list.get(i);
threadPool.execute(new Runnable() {
@Override
public void run() {
local.set(p);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 的Person为:"+ local.get() );
}
});
}
threadPool.shutdown();
}
}