虚拟线程(Virtual Thread)

1.什么是虚拟线程?

        虚拟线程是一种轻量级的线程,旨在解决传统资源占用较大、调度开销高的问题

        传统线程是由操作系统进行调度和管理的,而虚拟线程的调度由 Java 虚拟机(JVM)管理。虚拟线程并不由操作系统调度,而是由普通线程调度。

        一个操作系统可以调度成百上千个虚拟线程。

1.1虚拟线程的特点:

  • 轻量级资源:虚拟线程比传统的线程占用更少的资源
  • 高效调度:虚拟线程可以由少数操作系统线程调度,大大提高了多任务处理的效率
  • 自动挂起:当虚拟线程进行 IO操作时,他会自动挂起并让其它虚拟线程继续执行,直到 IO操作完成,虚拟线程才会恢复执行
  • 现有代码兼容:无缝替代传统线程

2.虚拟线程的使用方式:

2.1直接创建虚拟线程并立即执行

//1.创建虚拟线程并立即运行
        Thread thread1 = Thread.startVirtualThread(()->{

            System.out.println("Start virtual thread...");

            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println("End virtual thread...");
        });

2.2创建虚拟线程,并不立即执行

//2.创建虚拟线程,并不立即执行
        Thread thread2 = Thread.ofVirtual().unstarted(()->{
            System.out.println("Start virtual thread...");

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println("End virtual thread...");
        });

        //手动启动线程
        thread2.start();

2.3通过 ThreadFactory 创建虚拟线程

//3.通过 ThreadFactory 创建虚拟线程
        ThreadFactory threadFactory = Thread.ofVirtual().factory();

        Thread thread3 = threadFactory.newThread(() -> {
            System.out.println("Start virtual thread...");

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println("End virtual thread...");
        });

        //启动虚拟线程
        thread3.start();

2.4使用 Executor 服务来调度虚拟线程

 //4.使用 Executor 服务来调度虚拟线程
        ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor();

        //创建大量虚拟线程并提交到 Executor 中
        for (int i = 0; i < 10000; i++) {
            executorService.submit(()->{
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                System.out.println("End virtual thread");

                return true;
            });
        }

3.虚拟线程的性能对比:

3.1编写程序:

public class VirtualThread {
    public static void main(String[] args) throws InterruptedException{

        //使用虚拟线程测试:
        long virtualTime = virtualThreadTest();
        System.out.println("虚拟线程池执行耗时:" + virtualTime);

        //使用普通线程进行测试:
        long traditionalTime = traditionalThreadTest();
        System.out.println("普通线程池耗时:" +  traditionalTime);


        // 计算两种线程执行时间的差异
        long timeDifference = traditionalTime - virtualTime;
        // 输出性能差异和速度提升倍数
        System.out.println("\n性能差异:" + formatTime(timeDifference) +
                " (" + String.format("%.2f", (double)traditionalTime / virtualTime) + " 倍速度提升)");
    }


    //普通线程执行器
    private static long traditionalThreadTest() throws InterruptedException {
        // 记录开始时间
        long start = System.currentTimeMillis();
        // 创建一个固定大小为100的线程池
        try (ExecutorService executor = Executors.newFixedThreadPool(100)) {
            // 提交taskCount个任务到线程池
            for (int i = 0; i < 10000; i++) {
                executor.submit(VirtualThread::threadSleep);
            }
            // 关闭线程池,不再接受新任务
            executor.shutdown();
            // 等待所有任务完成,最多等待1小时
            executor.awaitTermination(1, TimeUnit.HOURS);
        }
        // 计算并返回总耗时
        return System.currentTimeMillis() - start;
    }


    //虚拟线程执行器
    public static long virtualThreadTest(){
        long start = System.currentTimeMillis();

        //创建一个虚拟线程执行器
        try (ExecutorService es = Executors.newVirtualThreadPerTaskExecutor()){

            for (int i = 0; i < 10000; i++) {
                es.submit(VirtualThread::threadSleep);
            }

            //关闭线程池
            es.shutdown();

            //等待所有任务完成,最长为 1 HOURS
            es.awaitTermination(1, TimeUnit.HOURS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        return System.currentTimeMillis() - start;
    }


    public static void threadSleep(){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            //重新设置中断状态
            Thread.currentThread().interrupt();
        }
    }


    // 格式化时间的方法,将毫秒转换为更易读的格式
    private static String formatTime(long milliseconds) {
        // 返回格式化的字符串,同时显示毫秒数和秒数(保留两位小数)
        return String.format("%d 毫秒 (%.2f 秒)", milliseconds, milliseconds / 1000.0);
    }
}

3.2测试结果:

3.3结果分析:

  1. 执行时间:
    1. 传统线程:约1分40秒
    2. 虚拟线程:约1.99秒
  2. 性能提升:
    1. 虚拟线程比传统线程快约50.44倍
  3. 并发处理:
    1. 传统线程池限制为100个线程,导致任务需要分批处理
    2. 虚拟线程能够同时处理所有 10000个任务,显著减少了总执行时间
  4. 资源利用:
    1. 虚拟线程更有效地利用了系统资源,特别是在 I/O 密集型任务时

总结:

  1. 显著的性能优势:在这个 I/O 密集型的测试场景中,虚拟线程比传统线程执行速度提升了 50 倍
  2. 适用于高并发场景:虚拟线程特别适合处理大并发任务而不会耗尽系统资源
  3. 资源效率:虚拟线程能更有效地利用系统资源,允许创建大量并发任务而不会耗尽系统资源

虚拟线程Virtual Threads)是 Java 21 引入的一项新技术,作为 Project Loom 的核心成果,它彻底改变了并发编程范式,以轻量级、高吞吐的特性显著提升性能,尤其在 I/O 密集型任务中表现卓越 [^2]。 在传统线程模型下,高并发场景如电商平台的订单处理或实时推荐系统,因资源开销和上下文切换瓶颈难以满足性能需求。而虚拟线程的出现解决了这些问题 [^2]。其原理在于虚拟线程是由 Java 虚拟机(JVM)管理的轻量级线程,它们可以在少量的操作系统线程上运行,减少了资源开销和上下文切换的成本。一个操作系统线程可以支撑大量的虚拟线程,从而实现了高并发处理。 虚拟线程的应用场景广泛,尤其适用于 I/O 密集型任务。例如在电商平台的订单处理接口,使用虚拟线程能优化性能。2025 年,有零售系统通过虚拟线程优化了订单处理接口,吞吐量提升 3 倍,响应延迟降低 50% [^2]。在实时推荐系统中,虚拟线程也能够提升系统的响应速度和处理能力。 在实际应用中,还涉及到一些使用技巧。比如创建定制化虚拟线程池: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class VirtualThreadExample { public static void main(String[] args) { ExecutorService customExecutor = Executors.newThreadPerTaskExecutor( Thread.ofVirtual() .name("vt-", 1) .factory() ); } } ``` 异常处理策略可参考如下代码: ```java public class VirtualThreadExceptionHandling { public static void riskyOperation() { // 模拟可能抛出异常的操作 throw new RuntimeException("模拟异常"); } public static void main(String[] args) { Thread.startVirtualThread(() -> { try { riskyOperation(); } catch (Exception e) { System.err.println("⚠️ 错误捕获: " + e.getMessage()); } }); } } ``` 监控与调试方面,可以使用命令查看虚拟线程状态: ```bash jcmd <pid> Thread.dump_to_file -format=json vthreads.json ``` 可视化工具推荐使用 JDK Mission Control 或 VisualVM [^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值