2、ThreadLocal

我们知道线程之所以不安全是因为线程之间存在竞争,而存在竞争是因为它们共享资源。因此有时候,我们会需要将资源只在本线程内,资源只与相应的线程存在关系,那么就避免了线程不安全。

ThreadLocal就是一个将变量与特定的线程进行绑定的一个类,资源只会属于一个特定的线程。

ThreadLocal就是一个Map,它的键就是线程,值是资源变量。

 

这样的话,ThreadLocal就可以看成是一个局部变量。

 1 class MyTrehadData {
 2   private static ThreadLocal<MyThreadData> threadLocal=new ThreadLocal<MyThreadData>();
 3   private int data;
 4   private MyThreadData(){}
 5   
 6   public static MyThread getLocalThread() {
 7      MyThreadData instance=threadLocal.get();
 8      if(instance==null) {
 9          instance=new MyThreadData();
10          threadLocal.set(instance);
11      }
12      return instance;
13   }
14 
15   public int getData() {
16        return data;
17   }
18  
19   public void setData(int data) {
20       this.data=data
21   }
22 }
 1 public class ThreadScopeShare {
 4    public static void main(String[]args) {
 5       new ThreadScopseShare().init();
 6    }
 7 
 8    public void init() {
 9       for(int i=0;i<2;i++)  {
10           new Thread(new Runnable() {
11                public void run() {
12                    MyThreadData myData=MyThreadData.getLocalThread();
13                    myData.setData(new Random().nextInt());
14                    System.out.println(Thread.currentThread().getName()+" set data:"+myData.getData());16                    new A().get();
17                    new B().get();
18                }
19           });
20       }
21    }
22 
23    class A {
24        public void get() {
25           MyThreadData myData=myThreadData.getLocalThread();
26           System.out.println("A from "+Thread.currentThread().getName()+" get data:"+myData.getData());
27        }
28    }
29   
30   
31    class B {
32          public void get() {
33           MyThreadData myData=myThreadData.getLocalThread();
34           System.out.println("B from "+Thread.currentThread().getName()+" get data:"+myData.getData());
35     }
36 }

在这里类MyThreadData是一个单例(当然不是严格意义上的单例),而且MyThreadData的属性ThreadLocal属于类所有,也就是说所有的线程都会是同一个ThreadLocal。只是ThreadLocal当中的空间

是与该线程相关的。

ThreadLocal类提供了get和set方法往这个容器当中取值和设置值。其实就是看哪个线程跑这段代码,那么就会根据这个线程的名字去设置或者取出它相应的值(根据线程名去进行操作这是一种隐性操作)。

于是,这个程序的含义就是:有两个线程1和2,它们都会往ThreadLocal当中放入相应的随机值。只是线程1放入随机值时,是以"Thread-1"作为键;线程2放入随机值时,是以"Thread-2"作为键。

当从ThreadLocal里面取值时,如果是线程1跑这段代码,那么就会以键"Thread-1"来取相应的值;反之如果是线程2来跑这段代码,那么就会以"Thread-2"来取相应的值。

 

posted on 2015-05-26 16:18  飞机说之代码也疯狂  阅读(159)  评论(0编辑  收藏  举报