ThreadLocal的特点
1. ThreadLocal 可以实现【资源对象】的线程隔离,让每个线程各用各的【资源对象】,避免引用引起的线程安全问题
2. ThreadLocal 同时实现线程内资源共享(一个线程里面)
ThreadLocal的特原理:
(1)调用set方法,就是以 ThreadLocal 自己作为key,资源对象作为 value,放入当前线程的 ThreadLocalMap 集合中
(2)调用get方法,就是以 ThreadLocal自己作为key,到当前线程中查找关联的资源值
(3)调用 remove方法,就是以 ThreadLocal自己作为key,移除当前线程关联的资源值
为什么 ThreadLocal中的key(即 ThreadLocal)要设计为弱引用?
(1)Thread可能需要长时间运行(如线程池中的线程),如果key不在使用,需要再内存不足(GC)时释放其占用的内存
()但GC是让key的内存释放,后续还要根据key是否为null来进一步释放值的内存,其释放的时机有:
1)获取key发现 null key
2) set key时,会使用启发式扫描,清除临近的 null key,启发次数与元素个数,受否发现 null key 有关
3) remove时(土建使用);一般 ThreadLocal都作为静态变量,因此GC无法回收
ThreadLocal的特点代码示例:
package com.irving.list;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* @author zdq
* @version 1.0
* @date 2022/5/16 15:42
* @describe
*/
public class ThreadLocalStudy {
public static void main(String[] args) throws InterruptedException {
test1(); // 多线程下,实现【资源对象】的线程隔离
test2(); // 一个线程,实现线程内资源共享
}
// 单个线程
public static void test2(){
for (int i = 0; i <2 ; i++) {
new Thread(()->{
System.out.println(utils.getConnection());
System.out.println(utils.getConnection());},"t").start();
}
}
// 多个线程
public static void test1(){
for (int i = 0; i <5 ; i++) {
new Thread(()->System.out.println(utils.getConnection()),"t"+(i+1)).start();
}
}
static class utils{
private static final ThreadLocal<Connection> t1=new ThreadLocal<>();
public static Connection getConnection(){
Connection connection = t1.get(); // 当前线程获取资源
if(connection==null){
connection = getCon(); //
t1.set(connection); //将资源存入当前线程
}
return connection;
}
}
private static Connection getCon(){
try {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/imapi?useSSL=false","root","root");
}catch (SQLException e){
throw new RuntimeException();
}
}
}