标签:threadlocal
import java.util.concurrent.atomic.AtomicInteger; public class ThreadId { // Atomic integer containing the next thread ID to be assigned private static final AtomicInteger nextId = new AtomicInteger(0); // Thread local variable containing each thread's ID private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() { @Override protected Integer initialValue() { return nextId.getAndIncrement(); } }; // Returns the current thread's unique ID, assigning it if necessary public static int get() { return threadId.get(); } }每个线程都保持对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。
public class SimpleThreadLocal { private final Map valueMap = Collections.synchronizedMap(new HashMap()); public void set(Object newValue) { //键为线程对象,值为本线程的变量副本 valueMap.put(Thread.currentThread(), newValue); } public Object get() { Thread currentThread = Thread.currentThread(); //返回本线程对应的变量 Object o = valueMap.get(currentThread); //如果在Map中不存在,放到Map中保存起来 if (o == null && !valueMap.containsKey(currentThread)) { o = initialValue(); valueMap.put(currentThread, o); } return o; } public void remove() { valueMap.remove(Thread.currentThread()); } public Object initialValue() { return null; } }
public class SequenceNumber { // 通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值 private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() { @Override public Integer initialValue() { return 0; } }; // 获取下一个序列值 public int getNextNum() { seqNum.set(seqNum.get() + 1); return seqNum.get(); } public static void main(String[] args) { SequenceNumber sn = new SequenceNumber(); // 3个线程共享sn,各自产生序列号 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 final SequenceNumber sn; public TestClient(SequenceNumber sn) { this.sn = sn; } @Override public void run() { //每个线程打出3个序列值 for (int i = 0; i < 3; i++) { System.out.println("thread[" + Thread.currentThread().getName() + "] sn[" + sn.getNextNum() + "]"); } } } }考查下面输出的结果信息,我们发现每个线程所产生的序号虽然都共享同一个Sequence Number实例,但它们并没有发生相互干扰的情况,而是各自产生独立的序列号,这是因为我们通过ThreadLocal为每一个线程提供了单独的副本。
thread[Thread-1] sn[1] thread[Thread-1] sn[2] thread[Thread-0] sn[1] thread[Thread-2] sn[1] thread[Thread-0] sn[2] thread[Thread-0] sn[3] thread[Thread-1] sn[3] thread[Thread-2] sn[2] thread[Thread-2] sn[3]
标签:threadlocal
原文地址:http://blog.csdn.net/lgcssx/article/details/35369947