类ThreadLocal主要解决的就是每个线程绑定自己的值,可以将ThreadLocal类比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。
变量在不同线程间具有隔离性,也就是不同线程拥有自己的值,不同线程中的值是可以放入ThreadLocal类中进行保存的。
下面代码来验证线程变量的隔离性:
public class Test { public static void main(String[] args) { try { ThreadA a = new ThreadA(); a.start(); Thread.sleep(2000); ThreadB b = new ThreadB(); b.start(); Thread.sleep(2000); if (Tools.threadLocal.get() == null) { Tools.threadLocal.set(new Date()); } System.out.println(" Main get value " + Tools.threadLocal.get()); } catch (InterruptedException ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); } } } class ThreadA extends Thread { @Override public void run() { try { if (Tools.threadLocal.get() == null) { Tools.threadLocal.set(new Date()); } System.out.println("ThreadA get value " + Tools.threadLocal.get()); Thread.sleep(100); } catch (InterruptedException ex) { Logger.getLogger(ThreadA.class.getName()).log(Level.SEVERE, null, ex); } } } class ThreadB extends Thread { @Override public void run() { try { if (Tools.threadLocal.get() == null) { Tools.threadLocal.set(new Date()); } System.out.println("ThreadB get value " + Tools.threadLocal.get()); Thread.sleep(100); } catch (InterruptedException ex) { Logger.getLogger(ThreadA.class.getName()).log(Level.SEVERE, null, ex); } } } class Tools { static ThreadLocal<Date> threadLocal = new ThreadLocal<Date>(); }
控制台打印结果如下:
ThreadA get value Fri Apr 07 16:00:59 CST 2017 ThreadB get value Fri Apr 07 16:01:01 CST 2017 Main get value Fri Apr 07 16:01:03 CST 2017
虽然3个线程都向threadLocal中set()数据值,但是每个线程还是能取出自己的数据。
在第一次调用ThreadLocal类的get()方法返回值是null,怎么样实现第一次调用get()不反悔null呢?也就是具有默认值的效果。
修改一下内部类Tools :
class Tools { static ThreadLocalExt<Date> threadLocal = new ThreadLocalExt<Date>(); } class ThreadLocalExt<V> extends ThreadLocal{ @Override protected Object initialValue() { return "Default value"; } }
控制台打印结果如下:
ThreadA get value Default value ThreadB get value Default value Main get value Default value
可见覆盖ThreadLocal类的initialValue()方法可以设置默认值。