前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 21正式发布 小小使用一下期待已久的虚拟线程

Java 21正式发布 小小使用一下期待已久的虚拟线程

原创
作者头像
Lorin 洛林
修改2023-11-08 21:47:11
5500
修改2023-11-08 21:47:11
举报
文章被收录于专栏:Java 技术小屋

前言

  • hello,大家好,我是Lorin,2023年9月19号,Java 21 通用版本正式发布,具体的版本内容可以参考下面这篇文章:
  • Java 21 版本特性一览:https://mp.weixin.qq.com/s/46VM8uRe6P697KnXHnUmcw
  • 其中也有一些比较好的特性,其中最让我感兴趣的就是虚拟线程,虚拟线程这个名字大家也许有点陌生,但是协程这个名字大家可能耳熟能详,从 Java 19 开始加入预览版,今天终于成为了正式版,我们来看看它究竟能给我们带来什么?

虚拟线程(协程)

  • 虚拟线程是一种轻量级的并发编程机制,它在代码中提供了一种顺序执行的感觉,同时允许在需要时挂起和恢复执行。虚拟线程可以看作是一种用户级线程,与操作系统的线程或进程不同,它是由编程语言或库提供的,而不是由操作系统管理的。
  • 看下面的图大家也许更容易理解:

优点

  • 非常轻量级:可以在单个线程中创建成百上千个虚拟线程而不会导致过多的线程创建和上下文切换。
  • 简化异步编程: 虚拟线程可以简化异步编程,使代码更易于理解和维护。它可以将异步代码编写得更像同步代码,避免了回调地狱(Callback Hell)。
  • 减少资源开销: 相比于操作系统线程,虚拟线程的资源开销更小。本质上是提高了线程的执行效率,从而减少线程资源的创建和上下文切换。

缺点

  • 不适用于计算密集型任务: 虚拟线程适用于I/O密集型任务,但不适用于计算密集型任务,因为密集型计算始终需要CPU资源作为支持。
  • 依赖于语言或库的支持: 协程需要编程语言或库提供支持。不是所有编程语言都原生支持协程。比如 Java 实现的虚拟线程。

使用 Java 虚拟线程

  • Java 21已经正式支持虚拟线程,大家可以在官网下载使用,在使用上官方为了降低使用门槛,尽量复用原有的 Thread 类,让大家可以更加平滑的使用。

如何创建虚拟线程

  • 官方提供了以下几种方式:

使用Thread.startVirtualThread()创建

代码语言:Java
复制
public class VirtualThreadTest { 
  public static void main(String[] args) { 
    CustomThread customThread = new CustomThread();
    Thread.startVirtualThread(customThread); 
  }
}

static class CustomThread implements Runnable { 
  @Override 
  public void run() { 
    System.out.println("CustomThread run"); 
  } 
}

使用Thread.ofVirtual()创建

代码语言:Java
复制
public class VirtualThreadTest {  
  public static void main(String[] args) { 
    CustomThread customThread = new CustomThread();
    // 创建不启动
    Thread unStarted = Thread.ofVirtual().unstarted(customThread);
    unStarted.start(); 
    // 创建直接启动
    Thread.ofVirtual().start(customThread); 
  }
}
static class CustomThread implements Runnable { 
  @Override
  public void run() { 
    System.out.println("CustomThread run"); 
  }
}

使用ThreadFactory创建

代码语言:Java
复制
public class VirtualThreadTest { 
  public static void main(String[] args) { 
    CustomThread customThread = new CustomThread();
    ThreadFactory factory = Thread.ofVirtual().factory();
    Thread thread = factory.newThread(customThread);
    thread.start(); 
  }
}

static class CustomThread implements Runnable {
  @Override
  public void run() {
    System.out.println("CustomThread run");
  }
}

使用Executors.newVirtualThreadPerTaskExecutor()创建

代码语言:Java
复制
public class VirtualThreadTest {
  public static void main(String[] args) {
    CustomThread customThread = new CustomThread();
    ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
    executor.submit(customThread);
  }
}
static class CustomThread implements Runnable {
  @Override
  public void run() {
    System.out.println("CustomThread run");
  } 
}

性能对比

  • 通过多线程和虚拟线程的方式处理相同的任务,对比创建的系统线程数和处理耗时:
  • 注:统计创建的系统线程中部分为后台线程(比如 GC 线程),两种场景下都一样,所以并不影响对比。
代码语言:Java
复制
public class VirtualThreadTest {
    static List<Integer> list = new ArrayList<>();
    public static void main(String[] args) {
        // 开启线程 统计平台线程数
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
            ThreadInfo[] threadInfo = threadBean.dumpAllThreads(false, false);
            updateMaxThreadNum(threadInfo.length);
        }, 10, 10, TimeUnit.MILLISECONDS);

        long start = System.currentTimeMillis();
        // 虚拟线程
        ExecutorService executor =  Executors.newVirtualThreadPerTaskExecutor();
        // 使用平台线程
        // ExecutorService executor =  Executors.newFixedThreadPool(200);
        for (int i = 0; i < 10000; i++) {
            executor.submit(() -> {
                try {
                    // 线程睡眠 0.5 s,模拟业务处理
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException ignored) {
                }
            });
        }
        executor.close();
        System.out.println("max:" + list.get(0) + " platform thread/os thread");
        System.out.printf("totalMillis:%dms\n", System.currentTimeMillis() - start);


    }
    // 更新创建的平台最大线程数
    private static void updateMaxThreadNum(int num) {
        if (list.isEmpty()) {
            list.add(num);
        } else {
            Integer integer = list.get(0);
            if (num > integer) {
                list.add(0, num);
            }
        }
    }
}

请求数10000 单请求耗时 1s

代码语言:txt
复制
// Virtual Thread
max:22 platform thread/os thread
totalMillis:1806ms

// Platform Thread  线程数200
max:209 platform thread/os thread
totalMillis:50578ms

// Platform Thread  线程数500
max:509 platform thread/os thread
totalMillis:20254ms

// Platform Thread  线程数1000
max:1009 platform thread/os thread
totalMillis:10214ms

// Platform Thread  线程数2000
max:2009 platform thread/os thread
totalMillis:5358ms

请求数10000 单请求耗时 0.5s

代码语言:txt
复制
// Virtual Thread
max:22 platform thread/os thread
totalMillis:1316ms

// Platform Thread  线程数200
max:209 platform thread/os thread
totalMillis:25619ms

// Platform Thread  线程数500
max:509 platform thread/os thread
totalMillis:10277ms

// Platform Thread  线程数1000
max:1009 platform thread/os thread
totalMillis:5197ms

// Platform Thread  线程数2000
max:2009 platform thread/os thread
totalMillis:2865ms
  • 可以看到在密集 IO 的场景下,需要创建大量的平台线程异步处理才能达到虚拟线程的处理速度。
  • 因此,在密集 IO 的场景,虚拟线程可以大幅提高线程的执行效率,减少线程资源的创建以及上下文切换。
  • 吐槽:虽然虚拟线程我很想用,但是我 Java8 有机会升级到 Java21 吗?呜呜
代码语言:txt
复制
注:有段时间 JDK 一直致力于 Reactor 响应式编程来提高Java性能,但响应式编程难以理解、调试、使用,最终又回到了同步编程,最终虚拟线程诞生。

个人简介

👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.

🚀 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。

🧠 作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。

💡 在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。

🌐 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。

📖 保持关注我的博客,让我们共同追求技术卓越。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 虚拟线程(协程)
    • 优点
      • 缺点
      • 使用 Java 虚拟线程
        • 如何创建虚拟线程
          • 使用Thread.startVirtualThread()创建
          • 使用Thread.ofVirtual()创建
          • 使用ThreadFactory创建
          • 使用Executors.newVirtualThreadPerTaskExecutor()创建
        • 性能对比
          • 请求数10000 单请求耗时 1s
          • 请求数10000 单请求耗时 0.5s
      • 个人简介
      相关产品与服务
      云数据库 MySQL
      腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档