底层原理
1.1.ThreadLocal是java中所提供的线程本地存储机制,可以利用该机制将数据缓存到数据内部,该线程可以任务获取缓存中的数据
1.2.ThreadLocal底层是通过ThreadLocalMap来实现的,每个thread对象中都存在一个ThreadLocalMap,ThreadLocalMap的key是ThreadLocal对象,
ThreadLocalMap的value是需要缓存的值
1.3.如果在线程池中使用ThreadLocal会造成内存泄漏,因为线程池里面的线程使用不会立即销毁,
导致entry对象不会进行回收,所以使用完之后要调用ThreadLocal的方法手动清理entry对象
1 4.ThreadLocal经典的应用场景就是连接管理(一个线程持有一个连接,该连接对象在不同的方法之间进行传递,线程之间不共享一个连接)
方法介绍
get()获取ThreadLocal中当前线程共享变量的值
set()设置ThreadLocal中当前线程共享变量的值
remove()移除ThreadLocal中当前线程共享变量的值
initialValue() ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值
工具类
import java.util.HashMap;
import java.util.Map;
/**
* @author syl
*/
public class ThreadLocalUtils {
/**
* private static可以排除ThreadLocal的弱引用,
*/
private static final ThreadLocal<Map<String,Object>> THREAD_LOCAL=new ThreadLocal(){
@Override
protected Object initialValue() {
System.out.println("值为空");
return null;
}
};
/**
* 通过key获取数据
* @param key
* @return Object
*/
public static Object getData(String key){
Map map= THREAD_LOCAL.get();
if (map==null){
return null;
}
return map.get(key);
}
/**
* 设置值
* @param key
* @param value
*/
public static void setData(String key,Object value){
Map map= THREAD_LOCAL.get();
if (map==null){
map=new HashMap<String,Object>();
map.put(key,value);
THREAD_LOCAL.set(map);
}
map.put(key, value);
}
/**
* 清空当前线程所有的变量
*/
public static void remove(){
THREAD_LOCAL.remove();
}
/**
* 清除当前线程指定的变量
* @param key
*/
public static void remove(String key){
Map map= THREAD_LOCAL.get();
if (map!=null){
map.remove(key);
}
}
public static void main(String[] args) {
//测试线程之间数据不共享,只能从自己的线程获取/删除/设置数据
//在不同线程之间调用
twoThread();
//在同一线程调用
oneThread();
}
/**
* 在同一线程之间调用
*/
private static void oneThread() {
new Thread("3"){
@Override
public void run() {
main1();
main2();
}
}.start();
}
/**
* 在不同线程之间调用
*/
private static void twoThread() {
Thread t1= new Thread("1") {
@Override
public void run() {
main1();
}
};
Thread t2= new Thread("2") {
@Override
public void run() {
try {
//让线程顺序执行,让join的线程先执行完再执行当前线程
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
main2();
}
};
t1.start();
t2.start();
}
public static void main1() {
ThreadLocalUtils.setData("a", "zyp");
String name = Thread.currentThread().getName();
System.out.println("当前线程名"+name);
Object a = ThreadLocalUtils.getData("a");
System.out.println(a);
}
public static void main2() {
String name = Thread.currentThread().getName();
System.out.println("当前线程名"+name);
Object a = ThreadLocalUtils.getData("a");
if (a==null){
System.out.println("不同线程之间数据不共享");
}else {
System.out.println("同一线程数据共享,值为"+a);
}
}
}