ThreadLocal可以很方便的实现线程范围内的共享变量,ThreadLocal类就相当于一个Map。下面具体看这个类如何使用:
- 1-1 利用ThreadLocal实现线程范围内的共享变量
- import java.util.Hashtable;
- import java.util.Map;
- import java.util.Random;
- /*
- 每个线程拥有自己独立的数据
- 一个ThreadLocal代表一个变量,故其中只能放一个数据。
- */
- public class ThreadLocalTest {//三个模块中的一个;
- private static ThreadLocal<Integer> x=new ThreadLocal<Integer>();//x变量名
- //ThreadLocal里边存放MyThreadScopeData数据
- 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();
- System.out.println(Thread.currentThread().getName()
- +"has put data :"+data);
- x.set(data);//往当前线程中放数据,与当前线程相关的,不是全局的
- MyThreadScopeData myData=new MyThreadScopeData();//new一个对象MyThreadScopeData()
- myData.setName("name"+data);//往myData里边存放数据
- myData.setAge(data);
- MyThreadScopeData.set(myData);//存数据
- new A().get();
- new B().get();
- }
- }){}.start();
- }
- }
- static class A{
- public void get(){
- int data=x.get();//取与当前线程有关的数据
- System.out.println("A from "+Thread.currentThread().getName()
- +" get data :"+data);
- MyThreadScopeData myData=MyThreadScopeData.get();//取数据,包括name和age
- System.out.println("A from "+Thread.currentThread().getName()
- +"getmyData :"+myData.getName()+","+
- myData.getAge());
- }
- }
- static class B{
- public void get(){
- int data=x.get();
- System.out.println("B from "+Thread.currentThread().getName()
- +" get data :"+data);
- }
- }
- }
- 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;
- }
- }
程序运行的结果如下:
上面的代码的整体思路:创建一个对象——放数据——取数据。代码组织的相当的糟糕,有没有一种优雅的实现实现方面呢?看下面的代码.
- 对代码1-1的改善,实现线程范围内的共享变量
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Random;
- public class ThreadLocalTest {
- private static ThreadLocal<Integer> x = 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();
- System.out.println(Thread.currentThread().getName()
- + " has put data :" + data);
- x.set(data);
- //得到与本线程有关的实力对象,在设置值
- MyThreadScopeData.getThreadInstance().setName("name" + data);
- MyThreadScopeData.getThreadInstance().setAge(data);
- new A().get();
- new B().get();
- }
- }).start();
- }
- }
- static class A{
- public void get(){
- int data = x.get();
- System.out.println("A from " + Thread.currentThread().getName()
- + " get data :" + data);
- MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();//得到与本线程有关的实例对象,在设置值
- System.out.println("A from " + Thread.currentThread().getName()
- + " getMyData: " + myData.getName() + "," +
- myData.getAge());
- }
- }
- static class B{
- public void get(){
- int data = x.get();
- System.out.println("B from " + Thread.currentThread().getName()
- + " get data :" + data);
- MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();//得到与本线程有关的实例对象,在设置值
- System.out.println("B from " + Thread.currentThread().getName()
- + " getMyData: " + myData.getName() + "," +
- myData.getAge());
- }
- }
- }
- class MyThreadScopeData{//将实体转化成单例
- private MyThreadScopeData(){}//第一件事:构造方法私有化,让其它的没法创建它的实例对象
- public static /*synchronized*/ MyThreadScopeData getThreadInstance(){
- //利用静态方法,得到实例对象,synchronized时,在饥汉模式下
- MyThreadScopeData instance = map.get();
- if(instance == null){//饥汉模式,只有第一次时创建(需要的时候创建),以后直接饭回instance
- instance = new MyThreadScopeData();//注意饥汉模式下,可能第一个线程来
- //检查instance == null,就去创建(赋值),还没有返回的时候,CPU切换到第二个线程,第二个线程来检查,
- //创建(赋值),那么可能就出现,第二次赋值覆盖第一次赋值,所以要互斥synchronized
- map.set(instance);//将值存起来
- }
- return instance;//返回实例对象
- }
- //private static MyThreadScopeData instance = new MyThreadScopeData();//饱汉模式
- //private static MyThreadScopeData instance = null;//饥汉模式
- //装线程范围内的共享变量
- 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;
- }
- }
程序运行的结果:
每一请求(每一个线程),有一个容器对象,这个容器对象存放与这个请求有关的所有数据,struts2中会有这种思想。
转载于:https://blog.51cto.com/020618/1183595