多个模块在同一个线程中运行时要共享同一份数据,实现线程范围内的数据共享可以用Map。
JDK1.5提供了ThreadLocal类来方便实现线程范围内的数据共享,它的作用就相当于Map。
每个线程调用全局ThreadLocal对象的set方法,就相当于往其内部的map集合中增加一条记录,key就是各自的线程,value就是各自的set方法传进去的值。
在线程结束时可以调用ThreadLocal.clear()方法用来更快释放内存,也可以不调用,因为线程结束后也可以自动释放相关的ThreadLocal变量。
import java.util.HashMap; import java.util.Map; import java.util.Random; public class ThreadLocalTest { private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>(); public static void main(String[] args) { //创建两个线程 for(int i=0;i<2;i++){ new Thread(new Runnable() { @Override public void run() { //现在当前线程中修改一下数据,给出修改信息 int data=new Random().nextInt(); //Thread.currentThread()获取当前线程。 System.out.println(Thread.currentThread().getName()+" has put data:"+data); //将线程信息和对应数据存储起来 threadLocal.set(data); //使用两个不同的模块操作这个数据,看结果 new A().get(); new B().get(); } }).start(); } } static class A{ public void get(){ int data=threadLocal.get(); System.out.println("A from"+Thread.currentThread().getName()+" get data:"+data); } } static class B{ public void get(){ int data=threadLocal.get(); System.out.println("B from"+Thread.currentThread().getName()+" get data:"+data); } } }运行结果为:
Thread-0 has put data:-1595352605
Thread-1 has put data:-765849300
A fromThread-0 get data:-1595352605
A fromThread-1 get data:-765849300
B fromThread-0 get data:-1595352605
B fromThread-1 get data:-765849300
一个ThreadLocal对象只能记录一个线程内部的一个共享变量,需要记录多个共享数据,可以创建多个ThreadLocal对象,或者将这些数据进行封装,将封装后的数据对象存入ThreadLocal对象中。
import java.util.HashMap; import java.util.Map; import java.util.Random; public class ThreadLocalTest { private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>(); private static ThreadLocal<MythreadScopeData> mythreadScopeData=new ThreadLocal<MythreadScopeData>(); public static void main(String[] args) { //创建两个线程 for(int i=0;i<2;i++){ new Thread(new Runnable() { @Override public void run() { //现在当前线程中修改一下数据,给出修改信息 int data=new Random().nextInt(); //Thread.currentThread()获取当前线程。 System.out.println(Thread.currentThread().getName()+" has put data:"+data); //将线程信息和对应数据存储起来 threadLocal.set(data); MythreadScopeData mData=new MythreadScopeData(); mData.setName("name:"+data); mData.setAge(data); mythreadScopeData.set(mData); //使用两个不同的模块操作这个数据,看结果 new A().get(); new B().get(); } }).start(); } } static class A{ public void get(){ int data=threadLocal.get(); System.out.println("A from"+Thread.currentThread().getName()+" get data:"+data); MythreadScopeData mData=mythreadScopeData.get(); System.out.println("A from"+Thread.currentThread().getName() +" getMyData:"+mData.getName()+","+mData.getAge()); } } static class B{ public void get(){ int data=threadLocal.get(); System.out.println("B from"+Thread.currentThread().getName()+" get data:"+data); MythreadScopeData mData=mythreadScopeData.get(); System.out.println("B from"+Thread.currentThread().getName() +" getMyData:"+mData.getName()+","+mData.getAge()); } } } class MythreadScopeData{ private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
运行结果为:
Thread-0 has put data:1785375164
Thread-1 has put data:1981597103
A fromThread-0 get data:1785375164
A fromThread-1 get data:1981597103
A fromThread-0 getMyData:name:1785375164,1785375164
A fromThread-1 getMyData:name:1981597103,1981597103
B fromThread-0 get data:1785375164
B fromThread-1 get data:1981597103
B fromThread-0 getMyData:name:1785375164,1785375164B fromThread-1 getMyData:name:1981597103,1981597103
将上述代码进行优化:
将数据对象封装成单例,同时提供线程范围内的共享数据的设置和获取方法,提供已经封装好了的线程范围内的对象实例,使用时只需获取实例对象即可实现数据的线程范围内的共享,因为该对象已经是当前线程范围内的对象了。
演示代码如下:
import java.util.HashMap; import java.util.Map; import java.util.Random; public class ThreadLocalTest { private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>(); private static ThreadLocal<MythreadScopeData> mythreadScopeData=new ThreadLocal<MythreadScopeData>(); public static void main(String[] args) { //创建两个线程 for(int i=0;i<2;i++){ new Thread(new Runnable() { @Override public void run() { //现在当前线程中修改一下数据,给出修改信息 int data=new Random().nextInt(); //Thread.currentThread()获取当前线程。 System.out.println(Thread.currentThread().getName()+" has put data:"+data); //将线程信息和对应数据存储起来 threadLocal.set(data); /* MythreadScopeData mData=new MythreadScopeData(); mData.setName("name:"+data); mData.setAge(data); mythreadScopeData.set(mData); */ MythreadScopeData.getThreadInstance().setName("name:"+data); MythreadScopeData.getThreadInstance().setAge(data); //使用两个不同的模块操作这个数据,看结果 new A().get(); new B().get(); } }).start(); } } static class A{ public void get(){ int data=threadLocal.get(); System.out.println("A from "+Thread.currentThread().getName()+" get data:"+data); /*MythreadScopeData mData=mythreadScopeData.get(); System.out.println("A from"+Thread.currentThread().getName() +" getMyData:"+mData.getName()+","+mData.getAge());*/ MythreadScopeData mData=MythreadScopeData.getThreadInstance(); System.out.println("A from "+Thread.currentThread().getName() +" getMyData:"+mData.getName()+","+mData.getAge()); } } static class B{ public void get(){ int data=threadLocal.get(); System.out.println("B from "+Thread.currentThread().getName()+" get data:"+data); /*MythreadScopeData mData=mythreadScopeData.get(); System.out.println("B from"+Thread.currentThread().getName() +" getMyData:"+mData.getName()+","+mData.getAge());*/ MythreadScopeData mData=MythreadScopeData.getThreadInstance(); System.out.println("B from "+Thread.currentThread().getName() +" getMyData:"+mData.getName()+","+mData.getAge()); } } } class MythreadScopeData{ private MythreadScopeData(){} //创建单例模式 /* //方法一 public static MythreadScopeData getInstance(){ return instance; } private static MythreadScopeData instance=new MythreadScopeData(); //方法二 public static synchronized MythreadScopeData getInstance(){ if(instance==null){ instance =new MythreadScopeData(); } return instance; } private static MythreadScopeData instance=null; */ //仿照单例模式,建立单例线程 public static MythreadScopeData getThreadInstance(){ MythreadScopeData instance=map.get(); if(instance==null){ instance =new MythreadScopeData(); map.set(instance); } return instance; } private static ThreadLocal<MythreadScopeData> map=new ThreadLocal<MythreadScopeData>(); private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
运行结果为:
Thread-1 has put data:-594509613
Thread-0 has put data:-395209683
A from Thread-1 get data:-594509613
A from Thread-0 get data:-395209683
A from Thread-1 getMyData:name:-594509613,-594509613
A from Thread-0 getMyData:name:-395209683,-395209683
B from Thread-1 get data:-594509613
B from Thread-0 get data:-395209683
B from Thread-1 getMyData:name:-594509613,-594509613
B from Thread-0 getMyData:name:-395209683,-395209683