标签:
ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。
ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些。
当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。
所以,在Java中编写线程局部变量的代码相对来说要笨拙一些,因此造成线程局部变量没有在Java开发者中得到很好的普及。
实现原理:ThreadLocal是如何做到为每一个线程维护变量的副本的呢?
其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。
Thread 中有一个成员变量:ThreadLocal.Values localValues,通过在ThreadLocal中进行操作来维护Map变量:Map中元素的键为线程对象,而值对应线程的变量副本。
ThreadLocal:
1 /** 2 * Sets the value of this variable for the current thread. If set to 3 * {@code null}, the value will be set to null and the underlying entry will 4 * still be present. 5 * 6 * @param value the new value of the variable for the caller thread. 7 */ 8 public void set(T value) { 9 Thread currentThread = Thread.currentThread(); 10 Values values = values(currentThread); 11 if (values == null) { 12 values = initializeValues(currentThread); 13 } 14 values.put(this, value); 15 }
TreadLocal.Values:
/** * Per-thread map of ThreadLocal instances to values. */ static class Values { /** * Size must always be a power of 2. */ private static final int INITIAL_SIZE = 16; /** * Placeholder for deleted entries. */ private static final Object TOMBSTONE = new Object(); /** * Map entries. Contains alternating keys (ThreadLocal) and values. * The length is always a power of 2. */ private Object[] table; /** Used to turn hashes into indices. */ private int mask; /** Number of live entries. */ private int size; /** Number of tombstones. */ private int tombstones; /** Maximum number of live entries and tombstones. */ private int maximumLoad; /** Points to the next cell to clean up. */ private int clean; /** * Constructs a new, empty instance. */ Values() { initializeTable(INITIAL_SIZE); this.size = 0; this.tombstones = 0; } ... /** * Adds an entry during rehashing. Compared to put(), this method * doesn‘t have to clean up, check for existing entries, account for * tombstones, etc. */ void add(ThreadLocal<?> key, Object value) { for (int index = key.hash & mask;; index = next(index)) { Object k = table[index]; if (k == null) { table[index] = key.reference; table[index + 1] = value; return; } } } /** * Sets entry for given ThreadLocal to given value, creating an * entry if necessary. */ void put(ThreadLocal<?> key, Object value) { cleanUp(); // Keep track of first tombstone. That‘s where we want to go back // and add an entry if necessary. int firstTombstone = -1; for (int index = key.hash & mask;; index = next(index)) { Object k = table[index]; if (k == key.reference) { // Replace existing entry. table[index + 1] = value; return; } if (k == null) { if (firstTombstone == -1) { // Fill in null slot. table[index] = key.reference; table[index + 1] = value; size++; return; } // Go back and replace first tombstone. table[firstTombstone] = key.reference; table[firstTombstone + 1] = value; tombstones--; size++; return; } // Remember first tombstone. if (firstTombstone == -1 && k == TOMBSTONE) { firstTombstone = index; } } } ... }
区别于优势
ThreadLocal和线程同步机制相比有什么优势呢?
对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式:仅提供一份变量,让不同的线程排队访问
而ThreadLocal采用了“以空间换时间”的方式:为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
http://baike.baidu.com/link?url=-MFpxUiVxQ9NTDK_LF7J6G5-OfMUJMJdNcJMFQTZ7kYB_V0AbL9q0E9huPUw4h7rwfIYpBj9ZhbXaILG5DQ9Jq
标签:
原文地址:http://www.cnblogs.com/luow/p/4387081.html