线程范围内共享数据作用和目的:线程内的数据共享,即对于相同的程序代码,多个模块在同一个线程中运行时要共享一份数据,而在另外线程中运行时又共享另外一份数据。即不同的线程对应不同的数据。如下图:

每个线程调用全局ThreadLocal对象的set方法,将相当于往其内的map中增加一条记录,key分别是各自的线程,value是各自的set方法传进去的值。线程结束时可以调用ThreadLocal.clear()方法,这样做会更快地释放内存,不调用也可以,因为线程结束后也可以自动释放相关的ThreadLocal变量。

  • 1-1 一个线程范围内的数据共享的例子。
  1. import java.util.Hashtable; 
  2. import java.util.Map; 
  3. import java.util.Random; 
  4. /* 
  5.  * 每个线程拥有自己独立的数据 
  6.  */ 
  7. public class ThreadScopeShareData {//三个模块中的一个 
  8.     private static int data=0
  9.     //实现各模块独立的效果 
  10.     private static Map<Thread, Integer> threadData=new Hashtable<Thread,Integer>(); 
  11.     public static void main(String[] args) { 
  12.         for (int i = 0; i < 2; i++) {//两个线程 
  13.             new Thread(new Runnable() {//线程调用A模块和B模块 
  14.                 @Override 
  15.                 public void run() { 
  16.                     int data=new Random().nextInt(); 
  17.                     System.out.println(Thread.currentThread().getName() 
  18.                             +"has put data :"+data);//放进数据 
  19.                     threadData.put(Thread.currentThread(), data);//放数据 
  20.                     new A().get(); 
  21.                     new B().get(); 
  22.                      
  23.                 } 
  24.             }){}.start(); 
  25.         } 
  26.     } 
  27.      
  28.     static class A{//A模块 
  29.         public void get(){//取数据方法 
  30.             int data=threadData.get(Thread.currentThread());//取数据 
  31.             System.out.println("A from "+Thread.currentThread().getName() 
  32.                     +" get data :"+data); 
  33.         } 
  34.     } 
  35.      
  36.     static class B{//B模块 
  37.         public void get(){//取数据方法 
  38.             int data=threadData.get(Thread.currentThread());//取数据 
  39.             System.out.println("B from "+Thread.currentThread().getName() 
  40.                     +" get data :"+data); 
  41.         } 
  42.     } 

运行结果:

从运行结果可以看出:线程范围内的共享数据,不同的线程对应不同的数据,而同一数据相对不同的线程应该是一致的,不能出现同一数据对不同的对象(线程,模块)是不同的数据。

比如在银行的账户中:一个模块往账户转入,一个转出,两个动作要不都做,要不都不做(保持数据的一致性),两个对象访问这个数据应该是一样的数据。