线程副本为每个使用该变量的线程提供一个独立的变量副本,即多个线程操作同一个变量,互相不会影响对方的值。
- void set()设置当前线程的线程副本的值
- public T get()返回当前线程拥有的线程副本的值
- public void remove()将该线程的线程副本的值删除。需要注意的是该方法不是一定要显式调用的,当线程结束后,Java的垃圾回收机制也会起作用,但是显式调用可以加快内存的回收。
- protected T initialValue()返回该线程的线程副本的初始值。
直接看代码:
package com.server.example.util.thread.basic;
/**
* Created by Administrator on 2016/12/18.
* 线程副本的示例
*/
public class ThreadLocalDemo {
//通过匿名内部类的方式覆盖ThreadLocal的initialValue方法
private static ThreadLocal<Integer> num=new ThreadLocal<Integer>(){
@Override
public Integer initialValue(){
return 0;
}
};
public ThreadLocal<Integer> getThreadLocal(){
return num;
}
public int getNextNum(){
num.set(num.get()+1);//在这里对线程副本做递增操作
return num.get();
}
public static class TestClient extends Thread{
private ThreadLocalDemo threadLocalDemo;
public TestClient(ThreadLocalDemo threadLocalDemo){
this.threadLocalDemo=threadLocalDemo;
}
@Override
public void run(){
for (int i=0;i<3;i++){
System.out.println("thread["+Thread.currentThread().getName()+"]-->threadLocalDemo["+threadLocalDemo.getNextNum()+"]");
}
threadLocalDemo.getThreadLocal().remove();//每次使用完要删除线程副本,否则容易造成内存泄漏
}
}
public static void main(String[] args){
ThreadLocalDemo threadLocalDemo=new ThreadLocalDemo();
TestClient t1=new TestClient(threadLocalDemo);
TestClient t2=new TestClient(threadLocalDemo);
TestClient t3=new TestClient(threadLocalDemo);
t1.start();
t2.start();
t3.start();
}
}
ThreadLocal比synchronized同步机制解决线程安全问题更简单更方便,且拥有更高的并发性。
需注意:使用ThreadLocal,一般都是声明在静态变量中,如果不断地创建且不remove,将会导致内存泄漏,尤其是在高并发的web容器中。