飞道的博客

为什么jdk源码推荐ThreadLocal使用static

313人阅读  评论(0)

ThreadLocal是线程私有变量,本身是解决多线程环境线程安全,可以说单线程实际上没必要使用。

既然多线程环境本身不使用static,那么又怎么会线程不安全。所以这个问题本身并不是问题,只是有人没有理解ThreadLocal的真正使用场景,所以有此疑问。

看看jdk源码推荐ThreadLocal使用static吧:


  
  1. /**
  2. * This class provides thread-local variables. These variables differ from
  3. * their normal counterparts in that each thread that accesses one (via its
  4. * {@code get} or {@code set} method) has its own, independently initialized
  5. * copy of the variable. {@code ThreadLocal} instances are typically private
  6. * static fields in classes that wish to associate state with a thread (e.g.,
  7. * a user ID or Transaction ID).
  8. *
  9. * <p>For example, the class below generates unique identifiers local to each
  10. * thread.
  11. * A thread's id is assigned the first time it invokes {@code ThreadId.get()}
  12. * and remains unchanged on subsequent calls.
  13. * <pre>
  14. * import java.util.concurrent.atomic.AtomicInteger;
  15. *
  16. * public class ThreadId {
  17. * // Atomic integer containing the next thread ID to be assigned
  18. * private static final AtomicInteger nextId = new AtomicInteger(0);
  19. *
  20. * // Thread local variable containing each thread's ID
  21. * private static final ThreadLocal&lt;Integer&gt; threadId =
  22. * new ThreadLocal&lt;Integer&gt;() {
  23. * &#64;Override protected Integer initialValue() {
  24. * return nextId.getAndIncrement();
  25. * }
  26. * };
  27. *
  28. * // Returns the current thread's unique ID, assigning it if necessary
  29. * public static int get() {
  30. * return threadId.get();
  31. * }
  32. * }
  33. * </pre>
  34. * <p>Each thread holds an implicit reference to its copy of a thread-local
  35. * variable as long as the thread is alive and the {@code ThreadLocal}
  36. * instance is accessible; after a thread goes away, all of its copies of
  37. * thread-local instances are subject to garbage collection (unless other
  38. * references to these copies exist).
  39. *
  40. * @author Josh Bloch and Doug Lea
  41. * @since 1.2
  42. */
  43. public class ThreadLocal<T> {
  44. /**
  45. * ThreadLocals rely on per-thread linear-probe hash maps attached
  46. * to each thread (Thread.threadLocals and
  47. * inheritableThreadLocals). The ThreadLocal objects act as keys,
  48. * searched via threadLocalHashCode. This is a custom hash code
  49. * (useful only within ThreadLocalMaps) that eliminates collisions
  50. * in the common case where consecutively constructed ThreadLocals
  51. * are used by the same threads, while remaining well-behaved in
  52. * less common cases.
  53. */

这个是Josh Bloch和Doug Lea写的,再看看他们的著作:《Java并发编程实战》

再看看jdk中的官方文档: 

已经说的很明白了,再看看其他答案吧:

 

按照ThreadLocal类的定义

此类提供线程局部变量。这些变量与普通变量不同,每个访问一个线程(通过其get或set方法)的线程都有其自己的,独立初始化的变量副本。ThreadLocal实例通常是希望将状态与线程关联的类中的私有静态字段(例如,用户ID或事务ID)。

这意味着说2个线程t1t2执行someBMethod(),它们分别结束设置x1x2(的实例X)。现在,当t1come并执行时,someCMethod()它会获取x1(它是由它自己设置的)和gets 。t2x2

换句话说,只有一个静态实例是安全的ThreadLocal,因为在内部调用时它会执行类似的操作set

 

 

Java 源代码

  1. java.lang.Thread Class包含一个实例变量,如下所示。

    ThreadLocal.ThreadLocalMap threadLocals = null;

因为threadLocals变量是非静态的,所以应用程序中的每个线程(即Thread Class的每个实例)将拥有它自己的threadLocals映射副本

  1. 该映射的当前 ThreadLocal实例,而value是您作为参数传递给ThreadLocal.set()的值。

  2. 当您尝试在内部获取 as值时ThreadLocal.get(),它将从Current Thread的ThreadLocalMap获取。

简而言之,您是从当前线程对象获取&设置值,而不是ThreadLocal对象获取&设置值。

 


转载:https://blog.csdn.net/21aspnet/article/details/105021557
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场