Thread.currentThread() 表现
Thread.currentThread() performance
我有 Runnable 队列,在指定线程中一个一个地调用。
val queue = LinkedBlockingQueue<() -> Unit>()
val queueThread = thread {
while(true)
queue.take().invoke()
}
我还有添加 Runnable 并等待它完成的功能。
fun invokeOnQueueThread(toInvoke: () -> Unit){
if(Thread.currentThread() == queueThread)
toInvoke()
else {
queue.offer(toInvoke)
// Some waiting code...
}
}
我测试当前线程是否已经在我队列的线程中以防止不必要的锁定。
所以,问题是:
如果我非常非常频繁地调用此代码,Thread.currentThread()
会导致性能问题吗?
JDK 本身依赖于 Thread.currentThread()
的性能,因为这种方法在标准 Java class 库中被广泛使用:具体来说,在 ThreadLocal.get
, ReentrantLock.lock
和其他 java.util.concurrent 原语。
虽然 Thread.currentThread()
在 OpenJDK 中被标记为本地方法,但它不是真正的 JNI 方法,而是 JVM intrinsic。这意味着,JIT 编译器用高度优化的机器代码替换调用。
在大多数 CPU 架构(x64、ARM 等)上,HotSpot JVM 有一个专用的 CPU 寄存器用于保存指向当前线程的指针。不是 java.lang.Thread
,而是表示 Java 线程的内部 VM 结构。反过来,这个结构持有对相应 java.lang.Thread
对象的引用。因此,在 JIT-compiled 代码中,获取对当前线程的引用只是从专用寄存器指向的结构中加载一次。
例如在 x64 上,寄存器 R15 在执行 Java 代码时保存指向当前 VM 线程的指针,并且 Thread.currentThread()
调用被编译为类似于
mov 0x280(%r15),%r11
因此调用 Thread.currentThread()
并不比读取常规字段慢,应该不是性能问题。
我有 Runnable 队列,在指定线程中一个一个地调用。
val queue = LinkedBlockingQueue<() -> Unit>()
val queueThread = thread {
while(true)
queue.take().invoke()
}
我还有添加 Runnable 并等待它完成的功能。
fun invokeOnQueueThread(toInvoke: () -> Unit){
if(Thread.currentThread() == queueThread)
toInvoke()
else {
queue.offer(toInvoke)
// Some waiting code...
}
}
我测试当前线程是否已经在我队列的线程中以防止不必要的锁定。
所以,问题是:
如果我非常非常频繁地调用此代码,Thread.currentThread()
会导致性能问题吗?
JDK 本身依赖于 Thread.currentThread()
的性能,因为这种方法在标准 Java class 库中被广泛使用:具体来说,在 ThreadLocal.get
, ReentrantLock.lock
和其他 java.util.concurrent 原语。
虽然 Thread.currentThread()
在 OpenJDK 中被标记为本地方法,但它不是真正的 JNI 方法,而是 JVM intrinsic。这意味着,JIT 编译器用高度优化的机器代码替换调用。
在大多数 CPU 架构(x64、ARM 等)上,HotSpot JVM 有一个专用的 CPU 寄存器用于保存指向当前线程的指针。不是 java.lang.Thread
,而是表示 Java 线程的内部 VM 结构。反过来,这个结构持有对相应 java.lang.Thread
对象的引用。因此,在 JIT-compiled 代码中,获取对当前线程的引用只是从专用寄存器指向的结构中加载一次。
例如在 x64 上,寄存器 R15 在执行 Java 代码时保存指向当前 VM 线程的指针,并且 Thread.currentThread()
调用被编译为类似于
mov 0x280(%r15),%r11
因此调用 Thread.currentThread()
并不比读取常规字段慢,应该不是性能问题。