1. public class Thread implements Runnable {
  2. ThreadLocal.ThreadLocalMap threadLocals = null;
  3. }

使用案例

  1. private void testThreadLocal() {
  2. Thread t = new Thread() {
  3. ThreadLocal<String> mStringThreadLocal = new ThreadLocal<>();
  4. @Override
  5. public void run() {
  6. super.run();
  7. mStringThreadLocal.set("droidyue.com");
  8. mStringThreadLocal.get();
  9. }
  10. };
  11. t.start();
  12. }

源码

  1. public void set(T value) {
  2. Thread t = Thread.currentThread();
  3. ThreadLocalMap map = getMap(t);
  4. if (map != null)
  5. map.set(this, value);
  6. else
  7. createMap(t, value);
  8. }
  9. ThreadLocalMap getMap(Thread t) {
  10. return t.threadLocals;
  11. }
  12. void createMap(Thread t, T firstValue) {
  13. t.threadLocals = new ThreadLocalMap(this, firstValue);
  14. }

实际上ThreadLocal的值是放入了当前线程的一个ThreadLocalMap实例中,所以只能在本线程中访问,其他线程无法访问。
在Java中,栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。
ThreadLocal的实例以及其值都是位于堆上,只是通过一些技巧将可见性修改成了线程可见。

使用InheritableThreadLocal可以实现多个线程访问ThreadLocal的值。

  1. private void testInheritableThreadLocal() {
  2. final ThreadLocal threadLocal = new InheritableThreadLocal();
  3. //主线程中设置
  4. threadLocal.set("droidyue.com");
  5. Thread t = new Thread() {
  6. @Override
  7. public void run() {
  8. super.run();
  9. //子线程中调用
  10. Log.i(LOGTAG, "testInheritableThreadLocal =" + threadLocal.get());
  11. }
  12. };
  13. t.start();
  14. }

使用InheritableThreadLocal可以将某个线程的ThreadLocal值在其子线程创建时传递过去。因为在线程创建过程中,有相关的处理逻辑。

  1. //Thread.java
  2. //thread的成员变量
  3. ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
  4. private void init(ThreadGroup g, Runnable target, String name,
  5. long stackSize, AccessControlContext acc) {
  6. //code goes here
  7. if (parent.inheritableThreadLocals != null)
  8. this.inheritableThreadLocals =
  9. ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
  10. /* Stash the specified stack size in case the VM cares */
  11. this.stackSize = stackSize;
  12. /* Set thread ID */
  13. tid = nextThreadID();
  14. }

ThreadLocal并不会产生内存泄露,因为ThreadLocalMap在选择key的时候,并不是直接选择ThreadLocal实例,而是ThreadLocal实例的弱引用。

  1. static class ThreadLocalMap {
  2. /**
  3. * The entries in this hash map extend WeakReference, using
  4. * its main ref field as the key (which is always a
  5. * ThreadLocal object). Note that null keys (i.e. entry.get()
  6. * == null) mean that the key is no longer referenced, so the
  7. * entry can be expunged from table. Such entries are referred to
  8. * as "stale entries" in the code that follows.
  9. */
  10. static class Entry extends WeakReference<ThreadLocal<?>> {
  11. /** The value associated with this ThreadLocal. */
  12. Object value;
  13. Entry(ThreadLocal<?> k, Object v) {
  14. super(k);
  15. value = v;
  16. }
  17. }
  18. }

使用

  • 实现单个线程单例以及单个线程上下文信息存储,比如交易id等。
  • 实现线程安全,非线程安全的对象使用ThreadLocal之后就会变得线程安全,因为每个线程都会有一个对应的实例。
  • 承载一些线程相关的数据,避免在方法中来回传递参数。