java.lang.Thread中的新增附加字段,有什么想法?
在Java 8中, java.lang.Thread
类有3个新字段:
/** The current seed for a ThreadLocalRandom */ @sun.misc.Contended("tlr") long threadLocalRandomSeed; /** Probe hash value; nonzero if threadLocalRandomSeed initialized */ @sun.misc.Contended("tlr") int threadLocalRandomProbe; /** Secondary seed isolated from public ThreadLocalRandom sequence */ @sun.misc.Contended("tlr") int threadLocalRandomSecondarySeed;
正如它在Javadoc中所说的那样,它是由java.util.concurrent.ThreadLocalRandom
类专门管理的。
此外,在ThreadLocalRandom
它们以非常奇怪的方式使用:
SEED = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomSeed")); PROBE = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomProbe")); SECONDARY = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
(在LockSupport
类中也LockSupport
相同的代码段)。
然后这个偏移在内部用于几个java.concurrent
地方。
这个想法是什么? 为什么这些字段是java.lang.Thread
? 为什么不在ThreadLocalRandom
?
这些是内部字段。 解释只能来自JDK开发人员自己。 我能够从2013年1月的Doug Lea找到一篇关于这个的post ,它解释了这些领域背后的基本原理以及它们在Thread
类中的原因。
当我们介绍
ThreadLocalRandom
,我们保守地实现它以使用实际的ThreadLocal
。 但是,随着它的使用越来越广泛,通过在Thread
类本身中容纳ThreadLocalRandom
状态(和相关的簿记)来改进实现是值得的。 这将需要三个字段(总共16个字节)。所以我建议在Thread类中添加以下内容:
// The following three initially uninitialized fields are exclusively // managed by class java.util.concurrent.ThreadLocalRandom. /** The current seed for a ThreadLocalRandom */ long threadLocalRandomSeed; /** Probe hash value; nonzero if threadLocalRandomSeed initialized */ int threadLocalRandomProbe; /** Secondary seed isolated from public ThreadLocalRandom sequence */ int threadLocalRandomSecondarySeed;
这样做的原因是:
对
ThreadLocalRandom
状态的访问速度更快。 虽然ThreadLocal
访问通常非常快,但这不仅更快,在用户程序创建大量ThreadLocal
的情况下也不会降低,这可能(概率上)导致任何给定访问变慢。使用
ThreadLocalRandom
任何程序的总占用空间更小。 三个字段比装入填充的ThreadLocal
对象所需的空间更少。 随着ThreadLocalRandom
在JDK中的广泛使用,这几乎包括所有程序。
java.util.concurrent ForkJoinPool
,ConcurrentHashMap
,LongAdder
,ConcurrentSkipList
以及其他类可以使用这种forms的统一ThreadLocalRandom
簿记而不是他们现在所使用的专用ThreadLocal
进一步节省时间/空间。
我将通过添加一个小答案来复活这个,因为我刚刚在LongAdder中看到这个,并且有一个很棒的video,Shipilev用简单的词语解释了这个(俄语),这里是链接: ThreadLocalRandom
对于ForkJoinPool的情况,它需要将任务放入队列并从队列中删除,该队列exaclty通过良好的PRNG解决。
这个程序必须非常快速和高度可扩展。 好吧,java有一个到位:ThreadLocalRandom。 要将这些字段放入ThreadLocalRandom,它需要一个ThreadLocal,而ThreadLocal又在内部使用ThreadLocalMap(想想HashMap)。
ThreadLocal.get(想想HashMap#get)比直接从Thread获取这些字段要慢得多。