ThreadLocal变量

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

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


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


来看一个实例:

  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. }  
public class SequenceNumber {
	// overwrite the ThreadLocal method initialValue() to set a initial value
	private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {
		public Integer initialValue() {
			return 0;
		}
	};

	// get next number
	public int getNextNum() {
		seqNum.set(seqNum.get() + 1);
		return seqNum.get();
	}

	public static void main(String[] args) {
		SequenceNumber sn = new SequenceNumber();
		// 3 threads use the same number variable and increase it
		TestClient t1 = new TestClient(sn);
		TestClient t2 = new TestClient(sn);
		TestClient t3 = new TestClient(sn);
		t1.start();
		t2.start();
		t3.start();
	}

	private static class TestClient extends Thread {
		private SequenceNumber sn;

		public TestClient(SequenceNumber sn) {
			this.sn = sn;
		}

		public void run() {
			for (int i = 0; i < 3; i++) {
				// every thread print 3 number
				System.out.println("thread[" + Thread.currentThread().getName()
						+ "] sn[" + sn.getNextNum() + "]");
			}
		}
	}
}

运行的结果如下:

  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]  
thread[Thread-2] sn[1]
thread[Thread-2] sn[2]
thread[Thread-2] sn[3]
thread[Thread-1] sn[1]
thread[Thread-1] sn[2]
thread[Thread-1] sn[3]
thread[Thread-0] sn[1]
thread[Thread-0] sn[2]
thread[Thread-0] sn[3]


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

  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. }  
public class TestThreadLocal {
   
	public static void main(String[] args) throws InterruptedException {
		// 两个线程共享字符串常量
		String ss = "xx";
		// 两个线程共享引用类型变量
		List l = new ArrayList();
		l.add("xxx");
		// 两个线程共享引用变量
		ThreadLocal<List<String>>  list = new ThreadLocal<List<String>>();
		list.set(new ArrayList<String>());
		
        new TestClient(ss,l,list).run();
        Thread.sleep(1000);
        System.out.println(ss + l +list.get());
	}
	private  static class TestClient extends Thread {
		private String sn;
        private List p;
        private ThreadLocal<List<String>> li;
		public TestClient(String sn,List p,ThreadLocal<List<String>> li) {
			this.sn = sn;
			this.p = p;
			this.li = li;
		}

		public void run() {
			sn = "bbbbbbb";
			
			for (int i = 0; i < 3; i++) {
				p.add("xxxx-" + i);
				li.get().add("th+"+i);
				System.out.println(sn + p);
			}
		}
	}
}

最后运行的结果如下:

  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]  
bbbbbbb[xxx, xxxx-0]
bbbbbbb[xxx, xxxx-0, xxxx-1]
bbbbbbb[xxx, xxxx-0, xxxx-1, xxxx-2]
xx[xxx, xxxx-0, xxxx-1, xxxx-2][th+0, th+1, th+2]

再来看一个例子,如下:

  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. }  
public class AbstractA {
     public void init(){
    	 List<String> l = new ArrayList<String>();
    	 l.add("张三");
    	 l.add("李四");
    	 if(DataStore.getList().get()==null){
    		 DataStore.getList().set(l);
    	 }
     }
}
  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. }  
public class ClassicB extends AbstractA{
	public void b() {
		init();
		DataStore.getList().get().add("a");
		DataStore.getList().get().add("b");
		// 打印结果
        System.out.println(DataStore.getList().get());
	}
}
  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. }  
public class Main {
	static ClassicB b = new ClassicB();
		
	public static void main(String[] args) {
		b.b();
		b.b();
		new SynchronizedTask().start();
		new SynchronizedTask().start();
	}

	private static  class SynchronizedTask extends Thread {
		public void run() {
			b.b();
		}
	}

}
最终运行的结果如下:

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


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








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值