下面的这一段代码运行起来,就会发生线程安全问题:
启动两个线程,同时去修改 name 属性值。
package com.liwei.thread; /** * 下面的代码演示了线程安全发生的由来 * * @author Administrator * */ public class ThreadLocalTest implements Runnable { private int i = 0; private String name = null; @Override public void run() { for (; i < 10; i++) { name = Thread.currentThread().getName(); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + name); } } public static void main(String[] args) { ThreadLocalTest tlt = new ThreadLocalTest(); Thread t1 = new Thread(tlt, "AAA"); Thread t2 = new Thread(tlt, "BBB"); t1.start(); t2.start(); } }
为了解决这个问题,我们给代码加上同步监视器,如下:
package com.liwei.thread; /** * 下面的代码演示了线程安全发生的由来 * * @author Administrator * */ public class ThreadLocalTest implements Runnable { private int i = 0; private String name = null; @Override public void run() { for (; i < 10000; i++) { synchronized (this) { name = Thread.currentThread().getName(); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + name); } } } public static void main(String[] args) { ThreadLocalTest tlt = new ThreadLocalTest(); Thread t1 = new Thread(tlt, "AAA"); Thread t2 = new Thread(tlt, "BBB"); t1.start(); t2.start(); } }
下面,我们的主角就要登场了,让我们来看看 ThreadLocal 的威力:
package com.liwei.thread; /** * 下面的代码演示了线程安全发生的由来 * * @author Administrator * */ public class ThreadLocalTest2 implements Runnable { private int i = 0; private ThreadLocal<String> threadLocal = new ThreadLocal<>(); @Override public void run() { for (; i < 100; i++) { threadLocal.set(Thread.currentThread().getName()); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + threadLocal.get()); } } public static void main(String[] args) { ThreadLocalTest2 tlt = new ThreadLocalTest2(); Thread t1 = new Thread(tlt, "CCC"); Thread t2 = new Thread(tlt, "DDD"); t1.start(); t2.start(); } }
我们通过看源码可以知道:ThreadLocalMap 以当前的 ThreadLocal 作为键。
参考资料:
ThreadLocal-分析-总结 - 洞玄 - ITeye技术网站
http://mxdba.iteye.com/blog/777716
深入浅出ThreadLocal - Java综合 - Java - ITeye论坛
http://www.iteye.com/topic/757478