在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
类中也可以满足相同的代码段。)
然后在几个java.concurrent
位置内部使用此偏移量。
这是什么想法?为什么这些字段位于java.lang.Thread
内?为什么不在ThreadLocalRandom
内?
答案 0 :(得分:6)
这些是内部字段。解释只能来自JDK开发人员自己。我从2013年1月的Doug Lea那里找到了post,这解释了这些字段背后的基本原理以及它们为什么都在Thread
课程内。
当我们介绍
ThreadLocalRandom
时,我们保守地说 实现它以使用实际的ThreadLocal
。然而, 随着它被广泛使用,它值得改进 住房ThreadLocalRandom
州的实施 课程Thread
本身(和相关的簿记)。 这将需要三个字段(总共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
s 可能(概率上)导致任何给定的访问变为 慢。使用
ThreadLocalRandom
的任何程序的总占用空间都较小。 三个字段比填充填充所需的空间更少ThreadLocal
对象。随着ThreadLocalRandom
被广泛使用 在JDK本身中,这几乎包括所有程序。- 醇>
java.util.concurrent ForkJoinPool
进一步节省时间/空间,ConcurrentHashMap
,LongAdder
,ConcurrentSkipList
等 可以使用统一ThreadLocalRandom
的这种形式的类 簿记而不是他们自己的专用ThreadLocal
正如他们现在所做的那样。
答案 1 :(得分:1)
我也会通过添加一个小答案来复活这个,因为我只是在LongAdder中点击了这个,并且有一个很棒的视频,Shipilev用简单的词语解释了这个(俄语),这里是链接:ThreadLocalRandom
对于ForkJoinPool的情况,它需要将任务放入队列并从队列中删除,该队列exaclty通过良好的PRNG解决。
这个程序必须非常快速且高度可扩展。好吧,java有一个到位:ThreadLocalRandom。要将这些字段放入ThreadLocalRandom,它需要一个ThreadLocal,而ThreadLocal又在内部使用ThreadLocalMap(想想HashMap)。
ThreadLocal.get(想想HashMap#get)比从Thread直接获取这些字段慢得多。