八、ThreadLocal
先看示例:
public class ThreadTest{ private static int num1 = 0; @Test public void m1(){ for(int i = 0 ;i<2;i++){ new Thread(new Runnable(){ @Override public void run() { num1= new Random().nextInt(); System.out.println(Thread.currentThread().getName()+": data : "+num1); new A(); } }).start(); } } class A{ public A() { System.out.println("A :"+Thread.currentThread().getName()+" data : "+num1); } } }
上面示例中,定义了一个类变量num1,创建两个线程分别给num1赋随机值然后打印,在内部类A中也对num1的值进行打印。整个过程中,变量num1为所有线程所共享,只要有一个线程将其值改变,其它线程的值也会跟着改变。那么问题就来了,在很多时候,我们在一个线程中处理的数据,仅希望它在当前线程中有效,而不受其它线程的影响。也就是说,数据仅在当前线程中传播。那么,该如何实现呢?
public class ThreadTest { /** * 当以一个map,用来存储当前线程的数据 */ private static Map<Thread,Integer> map = new HashMap<Thread,Integer>(); @Test public void m2(){ for(int i = 0 ;i<2;i++){ new Thread(new Runnable(){ @Override public void run() { int num2 = new Random().nextInt(); map.put(Thread.currentThread(), num2); //将值绑定到当前线程中。 System.out.println(Thread.currentThread().getName()+": data : "+num2); new B(); } }).start(); } } class B{ public B() { int num2 = map.get(Thread.currentThread()); //取出当前线程的共享变量 System.out.println("B :"+Thread.currentThread().getName()+" data : "+num2); } } }
上面的示例中,已经实现了在线程的范围内共享。但是,灵活性不足。在lang包下已经为我们实现了线程局部变量的类ThreadLocal。
public class ThreadLocal { /** * 创建一个线程局部变量 */ private static ThreadLocal<Integer> local = new ThreadLocal<Integer>(); @Test public void m3(){ for(int i = 0 ;i<2;i++){ new Thread(new Runnable(){ @Override public void run() { int num3 = new Random().nextInt(); local.set(num3); //线程局部变量赋值。 System.out.println(Thread.currentThread().getName()+": data : "+num3); new C(); } }).start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } class C{ public C() { int num3 = local.get(); //取出当前线程的局部变量 System.out.println("C :"+Thread.currentThread().getName()+" data : "+num3); } } }
版本四:这样写的好处自己体会。
public class ThreadLocalTest2 { @Test public void m4(){ for(int i = 0 ;i<5;i++){ new Thread(new Runnable(){ @Override public void run() { int num4 = new Random().nextInt(); System.out.println(Thread.currentThread().getName()+": data : "+num4); D d = D.getD(); d.setData(num4); d.printD(); } }).start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 将线程局部变量封装到一个类里面 */ class D{ private static ThreadLocal<D> current= new ThreadLocal<D>(); private int data; private D(){} public static D getD(){ if(current.get() == null){ current.set(new D()); } return current.get(); } public int getData() { return data; } public void setData(int data) { this.data = data; } public void printD(){ System.out.println(Thread.currentThread()+": D : data:"+data); }
}