优缺点和使用注意事项:
/*
* ThreadLocal 用于每一个线程都有一个次线程对应的副本。“以空间换时间” 占用内存,提高效率,节约处理时间,同时保证事物一致性
* ThreadLocal防止内存泄漏的做法-->弱引用:WeakReference extends WeakReference<ThreadLocal>
* 弱引用:引用对象如果不工作,JVM扫面到此现象后会回收引用数值,节省内存
* 强引用:eg String name = "zhangsan"; 一般对象如果不extends WeakReference都是强引用对象,特点是引用不消失,即使引用不工作了
* 引用值仍旧存在内存,不会被JVM回收掉
*
* 写代码建议: 使用ThreadLocal后,可以手动调用其remove()方法。
*
*/
业务要求:
多线程下,实现线程内,多业务下数据共享使用; 实现线程之间数据彼此隔离
应用案例: 银行多人汇款
图:
应用代码模拟---> 获取线程数据conn
public class ConnectionManager {
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
private ConnectionManager(){}
public static Connection getInstance(){
try {
Connection conn = threadLocal.get();
if(conn == null){
conn = DriverManager.getConnection("");//获取数据库连接对象
threadLocal.set(conn);
}
return conn;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
要点: 使用map将线程和线程内公共数据绑定起来
代码1 自定义实现:
package thread;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/**
* 1 实现线程范围内的数据共享
* 2 实现线程之间的数据隔离
* 3 使用map对象,将每个线程产生的数据放在map中,业务方法中 仅仅获取当前线程下的共享数据 达到2的目的
*
* @author zm
*
*测试结果:
Thread-0 has put data 757103510
A from Thread-0 the data is: 757103510
B from Thread-0 the data is: 757103510
Thread-1 has put data -150123253
A from Thread-1 the data is: -150123253
B from Thread-1 the data is: -150123253
*/
public class ScopeShareDataInThread {
//
public static int sharedata;
public static Map map = new HashMap();
public static void main(String[] args) {
final Businness businness = new Businness();
for(int i=0; i<2; i++) {
new Thread(new Runnable(){
@Override
public void run() {
sharedata = new Random().nextInt();
System.out.println(Thread.currentThread().getName() + " has put data " + sharedata);
map.put(Thread.currentThread(), sharedata);
businness.business1(sharedata,map);
businness.business2(sharedata,map);
}
}).start();
}
}
}
class Businness {
// 业务1
public void business1(int data,Map map){
System.out.println("A from " + Thread.currentThread().getName() + " the data is: " + map.get(Thread.currentThread()));
}
// 业务2
public void business2(int data,Map map){
System.out.println("B from " + Thread.currentThread().getName() + " the data is: " + map.get(Thread.currentThread()));
}
}
代码2 使用JDK提供的ThreadLocal类:
package thread;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/**
* 使用jdk提供的类来实现 线程内数据共享 线程间数据隔离
*
* threadLocal.set(sharedata) 会把数据放在当前线程中
* threadLocal.get() 回从当前线程中得到存放的数据
*
* 其实 threadLocal = map.put(Thread.currentThread(), youdata);
*
* 测试结果:
Thread-1 has put data 193003072
A from Thread-1 the data is: 193003072
B from Thread-1 the data is: 193003072
Thread-0 has put data -2012177886
A from Thread-0 the data is: -2012177886
B from Thread-0 the data is: -2012177886
* @author zm
*
*/
public class MyThreadLocal {
//
public static ThreadLocal threadLocal = new ThreadLocal();
public static int sharedata;
public static void main(String[] args) {
final Businness1 businness = new Businness1();
for(int i=0; i<2; i++) {
new Thread(new Runnable(){
@Override
public void run() {
sharedata = new Random().nextInt();
System.out.println(Thread.currentThread().getName() + " has put data " + sharedata);
threadLocal.set(sharedata);
businness.business1(threadLocal);
businness.business2(threadLocal);
}
}).start();
}
}
}
class Businness1 {
// 业务1
public void business1(ThreadLocal threadLocal){
System.out.println("A from " + Thread.currentThread().getName() + " the data is: " + threadLocal.get());
}
// 业务2
public void business2(ThreadLocal threadLocal){
System.out.println("B from " + Thread.currentThread().getName() + " the data is: " + threadLocal.get());
}
}
脑图: