ThreadLocal变量

来源:互联网 发布:js在线格式化工具 编辑:程序博客网 时间:2024/06/05 15:00

在做ThreadLocal时遇到了一件特别郁闷的事。因为ThreadLocal是线程独享的,但是我在做程序开发时却遇到一个问题,就是ThreadLocal里总是有另外一个线程插入的数据。最后终于发现,原来启动的两个线程都是main线程,不知道为什么。。。。。。。。。

clean项目,重启MyEclipse后,问题解决了。。。。。。。。。。


紧接着又一件郁闷事来了。在使用线程池时,如果某一个线路中运行含有ThreadLocal变量时,当将这个线程释放回线程池时,再次取出后,这时的ThreadLocal还会保存上次运行时的结果,而不会重置线程。所以我的程序出现有时正确、有时错误的状态。。。。。。。


来看一个实例:

[html] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class SequenceNumber {  
  2.     // overwrite the ThreadLocal method initialValue() to set a initial value  
  3.     private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {  
  4.         public Integer initialValue() {  
  5.             return 0;  
  6.         }  
  7.     };  
  8.   
  9.     // get next number  
  10.     public int getNextNum() {  
  11.         seqNum.set(seqNum.get() + 1);  
  12.         return seqNum.get();  
  13.     }  
  14.   
  15.     public static void main(String[] args) {  
  16.         SequenceNumber sn = new SequenceNumber();  
  17.         // 3 threads use the same number variable and increase it  
  18.         TestClient t1 = new TestClient(sn);  
  19.         TestClient t2 = new TestClient(sn);  
  20.         TestClient t3 = new TestClient(sn);  
  21.         t1.start();  
  22.         t2.start();  
  23.         t3.start();  
  24.     }  
  25.   
  26.     private static class TestClient extends Thread {  
  27.         private SequenceNumber sn;  
  28.   
  29.         public TestClient(SequenceNumber sn) {  
  30.             this.sn = sn;  
  31.         }  
  32.   
  33.         public void run() {  
  34.             for (int i = 0; i < 3; i++) {  
  35.                 // every thread print 3 number  
  36.                 System.out.println("thread[" + Thread.currentThread().getName()  
  37.                         + "] sn[" + sn.getNextNum() + "]");  
  38.             }  
  39.         }  
  40.     }  
  41. }  

运行的结果如下:

[html] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. thread[Thread-2] sn[1]  
  2. thread[Thread-2] sn[2]  
  3. thread[Thread-2] sn[3]  
  4. thread[Thread-1] sn[1]  
  5. thread[Thread-1] sn[2]  
  6. thread[Thread-1] sn[3]  
  7. thread[Thread-0] sn[1]  
  8. thread[Thread-0] sn[2]  
  9. thread[Thread-0] sn[3]  


如果两个线程要共享同一个变量,除了这个变量为静态变量外,还可以传递引用达到共享目的,如下:

[html] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class TestThreadLocal {  
  2.      
  3.     public static void main(String[] args) throws InterruptedException {  
  4.         // 两个线程共享字符串常量  
  5.         String ss = "xx";  
  6.         // 两个线程共享引用类型变量  
  7.         List l = new ArrayList();  
  8.         l.add("xxx");  
  9.         // 两个线程共享引用变量  
  10.         ThreadLocal<List<String>>  list = new ThreadLocal<List<String>>();  
  11.         list.set(new ArrayList<String>());  
  12.           
  13.         new TestClient(ss,l,list).run();  
  14.         Thread.sleep(1000);  
  15.         System.out.println(ss + l +list.get());  
  16.     }  
  17.     private  static class TestClient extends Thread {  
  18.         private String sn;  
  19.         private List p;  
  20.         private ThreadLocal<List<String>> li;  
  21.         public TestClient(String sn,List p,ThreadLocal<List<String>> li) {  
  22.             this.sn = sn;  
  23.             this.p = p;  
  24.             this.li = li;  
  25.         }  
  26.   
  27.         public void run() {  
  28.             sn = "bbbbbbb";  
  29.               
  30.             for (int i = 0; i < 3; i++) {  
  31.                 p.add("xxxx-" + i);  
  32.                 li.get().add("th+"+i);  
  33.                 System.out.println(sn + p);  
  34.             }  
  35.         }  
  36.     }  
  37. }  

最后运行的结果如下:

[html] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. bbbbbbb[xxx, xxxx-0]  
  2. bbbbbbb[xxx, xxxx-0, xxxx-1]  
  3. bbbbbbb[xxx, xxxx-0, xxxx-1, xxxx-2]  
  4. xx[xxx, xxxx-0, xxxx-1, xxxx-2][th+0, th+1, th+2]  

再来看一个例子,如下:

[html] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class AbstractA {  
  2.      public void init(){  
  3.          List<String> l = new ArrayList<String>();  
  4.          l.add("张三");  
  5.          l.add("李四");  
  6.          if(DataStore.getList().get()==null){  
  7.              DataStore.getList().set(l);  
  8.          }  
  9.      }  
  10. }  
[html] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class ClassicB extends AbstractA{  
  2.     public void b() {  
  3.         init();  
  4.         DataStore.getList().get().add("a");  
  5.         DataStore.getList().get().add("b");  
  6.         // 打印结果  
  7.         System.out.println(DataStore.getList().get());  
  8.     }  
  9. }  
[html] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class Main {  
  2.     static ClassicB b = new ClassicB();  
  3.           
  4.     public static void main(String[] args) {  
  5.         b.b();  
  6.         b.b();  
  7.         new SynchronizedTask().start();  
  8.         new SynchronizedTask().start();  
  9.     }  
  10.   
  11.     private static  class SynchronizedTask extends Thread {  
  12.         public void run() {  
  13.             b.b();  
  14.         }  
  15.     }  
  16.   
  17. }  
最终运行的结果如下:

[张三, 李四, a, b]
[张三, 李四, a, b, a, b]
[张三, 李四, a, b]
[张三, 李四, a, b]


可以看到ThreadLocal是每个线程独享的。








0 0
原创粉丝点击