是否有一种方法可以告诉虚拟线程运行在什么载波线程上?



我第一次玩项目织机,我有一些代码

try (var executor = Executors.newVirtualThreadExecutor()) {
IntStream.range(0, 16).forEach(i -> {
System.out.println("i = " + i + ", Thread ID = " + Thread.currentThread());
executor.submit(() -> {
System.out.println("Thread ID = " + Thread.currentThread());
});
});
}

输出类似

Thread ID = VirtualThread[#37]/runnable@ForkJoinPool-1-worker-4
Thread ID = VirtualThread[#33]/runnable@ForkJoinPool-1-worker-5
i = 9, Thread ID = Thread[#1,main,5,main]
Thread ID = VirtualThread[#43]/runnable@ForkJoinPool-1-worker-9
Thread ID = VirtualThread[#46]/runnable@ForkJoinPool-1-worker-11
i = 10, Thread ID = Thread[#1,main,5,main]
i = 11, Thread ID = Thread[#1,main,5,main]

是否有一种方法可以告诉我每个虚拟线程正在运行的载波线程?

ForkJoinPool-1-worker-11是否代表一个特定的载波(平台)线程,或者它是否意味着其他东西?

是的,这个后缀是当前载波线程的名称。

当我使用以下代码

public static void main(String[] args) throws InterruptedException {
Set<String> threadStrings = ConcurrentHashMap.newKeySet();
try(var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.invokeAll(Collections.nCopies(16,
() -> threadStrings.add(Thread.currentThread().toString())));
}
System.out.println("tSimple Run");
threadStrings.stream().sorted().forEachOrdered(System.out::println);
threadStrings.clear();
try(var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.invokeAll(Collections.nCopies(16, () -> {
threadStrings.add(Thread.currentThread().toString());
Thread.sleep(100);
return threadStrings.add(Thread.currentThread().toString());
}));
}
System.out.println("tWith wait");
threadStrings.stream().sorted().forEachOrdered(System.out::println);
}

它打印

Simple Run
VirtualThread[#15]/runnable@ForkJoinPool-1-worker-1
VirtualThread[#17]/runnable@ForkJoinPool-1-worker-2
VirtualThread[#18]/runnable@ForkJoinPool-1-worker-3
VirtualThread[#19]/runnable@ForkJoinPool-1-worker-4
VirtualThread[#20]/runnable@ForkJoinPool-1-worker-1
VirtualThread[#21]/runnable@ForkJoinPool-1-worker-1
VirtualThread[#22]/runnable@ForkJoinPool-1-worker-4
VirtualThread[#23]/runnable@ForkJoinPool-1-worker-1
VirtualThread[#24]/runnable@ForkJoinPool-1-worker-4
VirtualThread[#25]/runnable@ForkJoinPool-1-worker-4
VirtualThread[#26]/runnable@ForkJoinPool-1-worker-1
VirtualThread[#27]/runnable@ForkJoinPool-1-worker-4
VirtualThread[#28]/runnable@ForkJoinPool-1-worker-4
VirtualThread[#29]/runnable@ForkJoinPool-1-worker-1
VirtualThread[#30]/runnable@ForkJoinPool-1-worker-4
VirtualThread[#31]/runnable@ForkJoinPool-1-worker-4
With wait
VirtualThread[#36]/runnable@ForkJoinPool-1-worker-2
VirtualThread[#37]/runnable@ForkJoinPool-1-worker-3
VirtualThread[#37]/runnable@ForkJoinPool-1-worker-8
VirtualThread[#38]/runnable@ForkJoinPool-1-worker-4
VirtualThread[#38]/runnable@ForkJoinPool-1-worker-8
VirtualThread[#39]/runnable@ForkJoinPool-1-worker-1
VirtualThread[#39]/runnable@ForkJoinPool-1-worker-8
VirtualThread[#40]/runnable@ForkJoinPool-1-worker-5
VirtualThread[#40]/runnable@ForkJoinPool-1-worker-8
VirtualThread[#41]/runnable@ForkJoinPool-1-worker-6
VirtualThread[#41]/runnable@ForkJoinPool-1-worker-8
VirtualThread[#42]/runnable@ForkJoinPool-1-worker-7
VirtualThread[#42]/runnable@ForkJoinPool-1-worker-8
VirtualThread[#43]/runnable@ForkJoinPool-1-worker-5
VirtualThread[#43]/runnable@ForkJoinPool-1-worker-8
VirtualThread[#44]/runnable@ForkJoinPool-1-worker-1
VirtualThread[#44]/runnable@ForkJoinPool-1-worker-8
VirtualThread[#45]/runnable@ForkJoinPool-1-worker-5
VirtualThread[#45]/runnable@ForkJoinPool-1-worker-6
VirtualThread[#46]/runnable@ForkJoinPool-1-worker-5
VirtualThread[#46]/runnable@ForkJoinPool-1-worker-8
VirtualThread[#47]/runnable@ForkJoinPool-1-worker-2
VirtualThread[#49]/runnable@ForkJoinPool-1-worker-1
VirtualThread[#49]/runnable@ForkJoinPool-1-worker-8
VirtualThread[#50]/runnable@ForkJoinPool-1-worker-2
VirtualThread[#50]/runnable@ForkJoinPool-1-worker-6
VirtualThread[#51]/runnable@ForkJoinPool-1-worker-3
VirtualThread[#51]/runnable@ForkJoinPool-1-worker-5
VirtualThread[#52]/runnable@ForkJoinPool-1-worker-2
VirtualThread[#52]/runnable@ForkJoinPool-1-worker-8

(结果可能不同)

演示了在执行sleep时载波线程可能发生的变化。但在当前的快照("构建18-织机+6-282"),它是不可能指定自己的Executor了,也没有办法查询虚拟线程关于它使用的载体线程(除了通过toString()隐含的暗示)。因此,在这个版本中,底层主机线程的管理基本上是一个黑盒。

请记住,这是一个持续的发展。目前尚不清楚这种情况是否会改变,以及如何改变。

对于可重复使用的睡眠方法的自我注意:)_

将虚拟线程命名为'virtualThread-',然后检查名称是否以'virtualThread-'开头;https://davidvlijmincx.com/posts/naming-virtual-threads/

最新更新