标签:线程安全 并发 thread threadlocal struts2
ThreadLocal是一个和线程安全相关的类。package thread; public class NotSafeThread implements Runnable{ private int a=10; public void run() { // TODO Auto-generated method stub for (int i = 0; i < 5; i++) { try { if (Thread.currentThread().toString() .equals("Thread[t2,5,main]") && i == 2) Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().toString() + " a=" + a++); } } }
package thread; public class TestThread { public static void main(String[] args) { NotSafeThread nst=new NotSafeThread(); Thread t1=new Thread(nst,"t1"); Thread t2=new Thread(nst,"t2"); Thread t3=new Thread(nst,"t3"); t1.start(); t2.start(); t3.start(); } }输出的结果:a在各个线程中会累积。
public class SafaThread { private static ThreadLocal<Integer> counterContext=new ThreadLocal<Integer>(); public static Integer getCounterContext(){ if (counterContext.get()!=null) return counterContext.get(); setCounterContext(10); return counterContext.get(); } public static void setCounterContext(Integer value){ counterContext.set(value); } public static Integer getCounterContextNext(){ counterContext.set(getCounterContext()+1); return counterContext.get(); } }
package thread; public class ThreadLocalTest extends Thread{ public void run() { for (int i = 0; i < 5; i++) System.out.println(Thread.currentThread().getName()+" a="+ SafaThread.getCounterContextNext()); } public static void main(String[] args) { ThreadLocalTest t=new ThreadLocalTest(); Thread t1=new Thread(t); Thread t3=new Thread(t); Thread t2=new Thread(t); t1.start(); t2.start(); t3.start(); } }结果如下:
static class ThreadLocalMap { static class Entry extends WeakReference<ThreadLocal> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal k, Object v) { super(k); value = v; } } /** * The table, resized as necessary. * table.length MUST always be a power of two. */ private Entry[] table; ......//省略其他代码 }
Entry里面存放的是当前的ThreadLocal和这个线程中的成员变量。
当前线程的成员变量?怎么来的?public class Thread implements Runnable { /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null; ....//省略代码 }看到了吧,线程这个基类本身里面就有一个ThreadLocalMap。
System.out.println(Thread.currentThread().getName()+" a="+ SafaThread.getCounterContextNext());ok,进去
public static Integer getCounterContextNext(){ counterContext.set(getCounterContext()+1); return counterContext.get(); }最先执行的是getCounterContext()。
public static Integer getCounterContext(){ if (counterContext.get()!=null) return counterContext.get(); setCounterContext(10); return counterContext.get(); }我们看看counterContext(它本身是ThreadLocal<Integer>)的get方法。如下:
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); //标注1 if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); //标注3 if (e != null) return (T)e.value; } return setInitialValue(); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; }当我们第一次调用SafaThread.getCounterContextNext()的时候,直到上面的标注1处,返回的map肯定为空。我们看看setInitialValue
private T setInitialValue() { T value = initialValue(); //标注2 Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; }至于creatMap里面的代码
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }我们再看看ThreadLocalMap的构造函数。你妹呀,你想累死老子,都最后一步了,自己看!
protected T initialValue() { return null; }现在我们看看,看看什么?看ThreadLocal的set方法。中间的我不讲了。太累了。
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }跟get一样是吧。
static class Entry extends WeakReference<ThreadLocal> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal k, Object v) { super(k); value = v; } }key是ThreadLocal,value是要存储的值。
public class SafaThread { private static ThreadLocal<Integer> counterContext=new ThreadLocal<Integer>(); private static ThreadLocal<Integer> counterContext2=new ThreadLocal<Integer>(); ...//省略其他代码 本来有三个方法 现在就是六个 }本来只有一个变量,我现在放两个。
下一个应用
我们看看struts中是如何运用ThreadLocal的。
感谢glt
ThreadLocal最适合使用的场景:
在同一个线程的不同开发层次共享数据
使用ThreadLocal的步骤
1建立一个类,在其中封装静态的ThreadLocal变量,使其成为一个数据共享环境
2在类中实现ThreadLoca变量的静态方法(设值与取值)
先看a再看b
a: http://lavasoft.blog.51cto.com/62575/51926/
b: http://blog.csdn.net/lufeng20/article/details/24314381struts2技术内幕
标签:线程安全 并发 thread threadlocal struts2
原文地址:http://blog.csdn.net/dlf123321/article/details/42531979