有没有一种方法可以确定虚拟线程正在运行的载体线程是哪个?

4

我第一次尝试使用Project Loom,并编写了一些代码。

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代表特定的载体(平台)线程吗,还是代表其他意义?

2个回答

4

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

当我使用以下代码时

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 时承载线程可能会发生变化。但在当前的快照版本(“build 18-loom+6-282”)中,不再能够指定自己的 Executor,也没有方法查询虚拟线程使用的承载线程(除了通过 toString() 隐式提示)。因此,在这个版本中,底层主机线程的管理大多是一个黑盒子。

请记住,这是一个正在进行的开发过程。目前还不清楚这将如何改变。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接