虚拟线程(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. 资源效率:虚拟线程能更有效地利用系统资源,允许创建大量并发任务而不会耗尽系统资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值