Java-21推崇的虚拟线程到底有好快?一起来看这个实验

我们一起来看下面这个场景:十万个待执行任务,每个任务休眠两秒

1. 采用java-21的虚拟线程池来实现

    public static void main(String[] args) throws InterruptedException
    {
        ExecutorService VIRTUAL_THREAD_POOL = Executors.newThreadPerTaskExecutor(Thread.ofVirtual().name("Virtual-Thread#", 1).factory());
        
        // 定义任务数:十万个
        int total = 10 * 10000;
        CountDownLatch cdl = new CountDownLatch(total);
        long s = System.currentTimeMillis();
        for (int i = 0; i < total; i++)
        {
            VIRTUAL_THREAD_POOL.execute(() -> {
                try
                {
                    Thread.sleep(2000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                
                cdl.countDown();
            });
        }
        
        cdl.await();
        System.out.println("十万个任务执行完毕,总耗时:" + (System.currentTimeMillis() - s));
    }

最终输出:

十万个任务执行完毕,总耗时:3632

是的,你没看错,就只花了3.5秒左右,完成了10万个平均需要2秒才能完成的任务!

2. 采用原生线程池的效果

没有对比就没有伤害,我们一起再来看看用原生线程池的效果,大家先不要着急看结果,先猜测下,下面这段代码会发生什么呢?

    public static void main(String[] args) throws InterruptedException
    {
        // 定义任务数:十万个
        int total = 10 * 10000;
        ExecutorService THREAD_POOL = Executors.newFixedThreadPool(total);

        CountDownLatch cdl = new CountDownLatch(total);
        long s = System.currentTimeMillis();
        for (int i = 0; i < total; i++)
        {
            THREAD_POOL.execute(() -> {
                try
                {
                    Thread.sleep(2000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                
                cdl.countDown();
            });
        }
        
        cdl.await();
        System.out.println("十万个任务执行完毕,总耗时:" + (System.currentTimeMillis() - s));
    }

输出结果:
在这里插入图片描述是的,你没看错,运行近20秒后,直接内存崩溃了,要知道,我本机内存可是32G的物理机啊!!!都扛不住这10万个原生线程的开销

An unrecoverable stack overflow has occurred.
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x00007fff92212f83, pid=26344, tid=307540
#
# JRE version: OpenJDK Runtime Environment (22.0+36) (build 22+36-2370)
# Java VM: OpenJDK 64-Bit Server VM (22+36-2370, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64)
# Problematic frame:
# V  [jvm.dll+0x3e2f83][24.301s][warning][os,thread] Failed to start thread "Unknown thread" - _beginthreadex failed (EACCES) for attributes: stacksize: default, flags: CREATE_SUSPENDED STACK_SIZE_PARAM_IS.
[24.301s][warning][os,thread] Failed to start the native thread for java.lang.Thread "pool-1-thread-70502"
Exception in thread "main" java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached
	at java.base/java.lang.Thread.start0(Native Method)
	at java.base/java.lang.Thread.start(Thread.java:1540)
	at java.base/java.lang.System$2.start(System.java:2582)
	at java.base/jdk.internal.vm.SharedThreadContainer.start(SharedThreadContainer.java:152)
	at java.base/java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:953)
	at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1364)
	at com.sinhy.virtualthread.TestThreadSpeed2.main(TestThreadSpeed2.java:66)

3. 结论

java-21推崇的虚拟线程,是轻量级线程(类似于 Go 中的 “协程(Goroutine)”),可以减少编写、维护和调度高吞吐量并发应用程序的工作量。

与本地线程不同,虚拟线程并不有操作系统控制,虚拟线程是一个有JVM管理的用户态线程。对比于本地线程的高资源占用,每个虚拟线程只需要几个字节的内存空间。这是的它更适合控制管理大量的用户访问,或者说处理IO密集型任务。

在创建虚拟线程的数量上几乎没有限制,甚至可以创建一百万个,因为虚拟线程并不需要来自内核的系统调用。

在虚拟线程如此轻量化的条件下,线程池不再成为必须品,只需要在需要的时候尽情创建虚拟线程就好。

虚拟线程和传统的本地线程操作完全兼容,例如本地线程变量,同步块,线程中断,等等。

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙殿殿主

你的打赏是我精心创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值