6.ThreadLocal类及应用技巧

  1 import java.util.Random;
  2 
  3 /**
  4  * ThreadLocal类及应用技巧
  5  * *******************************************************************
  6  * 每个线程调用全局ThreadLocal对象的set方法,就相当于往其内部的map中增加一条记录,key
  7  * 分别是各自的线程,values是各自的set方法穿进去的值。在线程结束时可以调用ThreadLocal.clear();
  8  * 方法,这样会更快释放内存,不调用也可以,因为线程结束后也可以自动释放相关的ThreadLocal变量。
  9  * 实现对ThreadLocal变量的封装,让外界不要直接操作ThreadLocal变量
 10  *         对基本类型的数据的封装,这种应用相对少见。
 11  *         对对象类型的数据的封装,比较常见,即让某个类针对不同线程分别创建一个独立的实例对象。
 12  * 总结:
 13  *         一个ThreadLocal代表一个变量,故其中里只能放一个数据,你有两个变量都要线程范围内
 14  * 共享,则要定义两个ThreadLocal对象。如果有一百个变量要线程共享呢?把ThreadLocal封装
 15  * 到一个单例类中。
 16  * 
 17  * Struts2中的思想就是ThreadLocal模式
 18  * 
 19  * *******************************************************************
 20  * 虚拟机挂掉的时候注册钩子通知
 21  * Runtime->addShutdownHook(Thread hook) 
 22  * @author LiTaiQing
 23  */
 24 public class ThreadLocalTest {
 25     private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
 26     //private static ThreadLocal<MyThreadScopeData> myThreadScopeData = new ThreadLocal<MyThreadScopeData>();
 27     public static void main(String[] args){
 28         for(int i = 0; i < 2 ; i++){
 29             new Thread(new Runnable(){
 30                 @Override
 31                 public void run() {
 32                     int data = new Random().nextInt();
 33                     System.out.println(Thread.currentThread().getName() + " get put data :" + data);
 34                     threadLocal.set(data);
 35                     //myThreadScopeData.set(new MyThreadScopeData("name"+data,data));
 36                     MyThreadScopeData.getThreadInstance().setName("name" + data);
 37                     MyThreadScopeData.getThreadInstance().setAge(data);
 38                     new A().get();
 39                     new B().get();
 40                 }
 41             }).start();
 42         }
 43     }
 44     static class A{
 45         public void get(){
 46             int data = threadLocal.get();
 47             System.out.println("A from" + Thread.currentThread().getName() + " get put data :" + data);
 48             //MyThreadScopeData myData = myThreadScopeData.get();
 49             MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();
 50             System.out.println("A from" + Thread.currentThread().getName() + " getMyData :" + myData.getName()+","+myData.getAge());
 51         }
 52     }
 53     static class B{
 54         public void get(){
 55             int data = threadLocal.get();
 56             System.out.println("B from" + Thread.currentThread().getName() + " get put data :" + data);
 57             //MyThreadScopeData myData = myThreadScopeData.get();
 58             MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();
 59             System.out.println("B from" + Thread.currentThread().getName() + " getMyData :" + myData.getName()+","+myData.getAge());
 60         }
 61     }
 62 }
 63 class MyThreadScopeData{
 64     private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();
 65     //private static MyThreadScopeData instance = null;//new MyThreadScopeData();
 66     
 67     private MyThreadScopeData(){};
 68     /**
 69      * 这里可以不用synchronized,因为位于不同的线程内分别保存在ThreadLocal中
 70      * @return
 71      */
 72     public static /*synchronized*/ MyThreadScopeData getThreadInstance(){
 73         MyThreadScopeData instance = map.get();
 74         //这种方式容易出现多线程并发问题。所以最好采用饿汉模式
 75         if(instance==null){
 76             instance = new MyThreadScopeData();
 77             map.set(instance);
 78         }
 79         return instance;
 80     }
 81     
 82     private String name;
 83     private int age;
 84     
 85 //    public MyThreadScopeData(String name, int age) {
 86 //        super();
 87 //        this.name = name;
 88 //        this.age = age;
 89 //    }
 90     public String getName() {
 91         return name;
 92     }
 93     public void setName(String name) {
 94         this.name = name;
 95     }
 96     public int getAge() {
 97         return age;
 98     }
 99     public void setAge(int age) {
100         this.age = age;
101     }
102 }

 

posted @ 2015-07-10 11:10  登高一呼  阅读(440)  评论(0编辑  收藏  举报