在什么情况下,虚拟线程会扩展底层载体线程的数量?

Under what circumstances will virtual threads expand the number of underlying carrier threads?

提问人:FlyChenKai 提问时间:11/16/2023 更新时间:11/16/2023 访问量:49

问:

在 jep444 中,我看到“这些阻塞操作的实现通过临时扩展调度程序的并行性来补偿操作系统线程的捕获”。 在什么情况下,虚拟线程会扩展底层载体线程的数量?

你能给我一些代码来达到这个目的吗?

java-21 虚拟线程

评论

1赞 Holger 11/16/2023
也许当你使用很多的时候。synchronized
0赞 dan1st 11/16/2023
@Holger本身并不是一个大问题 - 但是阻止同步内部的操作会导致固定 - 但是,我不认为 OP 是在询问固定,而是像文件 I/O 这样的东西会暂时增加池中的平台线程数。synchronized
1赞 Holger 11/17/2023
@dan1st线程在拥有对象监视器的整个过程中被固定(不使用时为整个块),尽管您是对的,当线程不使用阻塞操作时,这不是问题。但请记住,当另一个线程拥有对象的监视器时,尝试进入块也是一个阻塞操作。因此,仅嵌套块(在不同对象上)就足以产生实际问题。synchronizedwaitsynchronizedsynchronized
0赞 dan1st 11/17/2023
从块固定不会暂时增加载体线程 IIRC 的数量。正如我所说,我认为 OP 正在询问尚未异步实现的事情。此外,如果您有高争用的嵌套块(即内部嵌套块是有争议的)或需要很长时间才能阻止的块,则可能做错了。synchronizedFileInputStreamsynchronizedsynchronized
0赞 FlyChenKai 11/29/2023
@dan1st 丹1st 你是对的,我不是在问固定。固定不会导致托架螺纹膨胀。我想知道什么操作会导致载体线程扩展。你能给我一些代码来达到这个吗?谢谢!

答:

0赞 FlyChenKai 12/1/2023 #1
public class CarrierThreadExpandTest {

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor();
        File file = new File("/Users/info.log");
        for (int i = 0; i < 32; i++) {
            executorService.execute(() -> {
                while (true) {
                    try (FileInputStream fis = new FileInputStream(file)) {
                        int content;
                        while ((content = fis.read()) != -1) {
                            System.out.print((char) content);
                        }
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }

                }
            });
        }
        Thread.sleep(1000 * 60 * 60);
    }
}

$ jps
$ jstack pid

查看“ForkJoinPool-1-worker-xx”线程。