Java SE 19 虚拟线程

作者:Grey

原文地址:

博客园:Java SE 19 虚拟线程

CSDN:Java SE 19 虚拟线程

说明

虚拟线程(Virtual Threads)是在Project Loom中开发的,并从 Java SE 19 开始作为预览功能引入 JDK。

在线程模型下,一个 Java 线程相当于一个操作系统线程,而这些线程是很消耗资源的,如果启动的线程过多,会给整个系统的稳定性带来风险。

虚拟线程解决了这个问题,从 Java 代码的角度来看,虚拟线程感觉就像普通的线程,但它们不是 1:1 地映射到操作系统线程上。

有一个所谓的载体线程池,一个虚拟线程被临时映射到该池中。一旦虚拟线程遇到阻塞操作,该虚拟线程就会从载体线程中移除,而载体线程可以执行另一个虚拟线程(新的或之前被阻塞的)。

所以阻塞的操作不再阻塞执行的线程。这使得我们可以用一个小的载体线程池来并行处理大量的请求。

示例

场景

启动 1000 个任务,每个任务等待一秒钟(模拟访问外部API),然后返回一个结果(在这个例子中是一个随机数)。

任务类如下

package git.snippets.vt;

import java.util.concurrent.Callable;
import java.util.concurrent.ThreadLocalRandom; /**
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2022/9/21
* @since 19
*/
public class Task implements Callable<Integer> { private final int number; public Task(int number) {
this.number = number;
} @Override
public Integer call() {
System.out.printf("Thread %s - Task %d waiting...%n", Thread.currentThread().getName(), number);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.printf("Thread %s - Task %d canceled.%n", Thread.currentThread().getName(), number);
return -1;
}
System.out.printf("Thread %s - Task %d finished.%n", Thread.currentThread().getName(), number);
return ThreadLocalRandom.current().nextInt(100);
}
}

接下来,我们测试使用线程池开启 100 个线程处理 1000 个任务需要多长时间。

package git.snippets.vt;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; /**
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2022/9/21
* @since 19
*/
public class App {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(100);
List<Task> tasks = new ArrayList<>();
for (int i = 0; i < 1_000; i++) {
tasks.add(new Task(i));
}
long time = System.currentTimeMillis();
List<Future<Integer>> futures = executor.invokeAll(tasks);
long sum = 0;
for (Future<Integer> future : futures) {
sum += future.get();
}
time = System.currentTimeMillis() - time;
System.out.println("sum = " + sum + "; time = " + time + " ms");
executor.shutdown();
}
}

运行结果如下

Thread pool-1-thread-1 - Task 0 waiting...
Thread pool-1-thread-3 - Task 2 waiting...
Thread pool-1-thread-2 - Task 1 waiting...
……
sum = 49879; time = 10142 ms

接下来,我们用虚拟线程测试整个事情。因此,我们只需要替换这一行

ExecutorService executor = Executors.newFixedThreadPool(100);

替换为

ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();

执行效果如下

Thread  - Task 0 waiting...
Thread - Task 2 waiting...
Thread - Task 3 waiting...
……
sum = 48348; time = 1125 ms

1125 ms VS 10142 ms,性能提升非常明显。

注:本示例需要在 JDK 19 下运行,且需要增加 --enable-preview 参数,在 IDEA 下,这个参数配置如下

我们已经了解了创建虚拟线程的一种方法:使用Executors.newVirtualThreadPerTaskExecutor()创建的执行器服务,为每个任务创建一个新的虚拟线程。

使用Thread.startVirtualThread()Thread.ofVirtual().start(),我们也可以明确地启动虚拟线程。

Thread.startVirtualThread(() -> {
// code to run in thread
}); Thread.ofVirtual().start(() -> {
// code to run in thread
});

特别说明:Thread.ofVirtual()返回一个VirtualThreadBuilder,其start()方法启动一个虚拟线程。另一个方法Thread.ofPlatform()返回一个PlatformThreadBuilder,通过它我们可以启动一个平台线程。

这两种构造方法都实现了Thread.Builder接口。这使得我们可以编写灵活的代码,在运行时决定它应该在虚拟线程还是平台线程中运行。

源码

hello-virtual-thread

参考资料

Java 19 Features (with Examples)

JDK 19 Release Notes

Virtual Threads in Java (Project Loom)

最新文章

  1. 计算bean的和(java)
  2. 还是不想改报告,伊阿忆啊哟-Linux基础继续
  3. http://blog.csdn.net/lipeng32768/article/details/50845547
  4. 用excel2010 制作复合图表
  5. windows下的go语言的环境搭建和初探
  6. C++ Dialog Box Command IDs
  7. Java学习随笔——RMI
  8. XSS完全解决方案
  9. ZOJ 3204 Connect them MST-Kruscal
  10. java泛型小问题
  11. VMware Workstation 12 Pro 之安装林耐斯Ubuntu X64系统
  12. 7.21.01 if语句
  13. 英语APP体验
  14. docker 学习之一:docker 安装
  15. 深度学习(Deep Learning)资料大全(不断更新)
  16. Codeforces Round #505 (Div 1 + Div 2 Combined) Solution
  17. 利用STM32CubeMX来生成USB_HID_Mouse工程【添加ADC】(2)【非dma和中断方式】
  18. Linux网络编程学习(六) ----- 管道(第四章)
  19. Lodop打印控件中PRINT_INITA()和PRINT_PAGESIZE()宽高
  20. React native 之android的图标和启动图片

热门文章

  1. Solution -「ABC 217」题解
  2. IM系统-消息流化一些常见问题
  3. DQL条件查询模糊查询和约束概述
  4. ExcelPatternTool: Excel表格-数据库互导工具
  5. 在centos7.6上部署前后端分离项目Nginx反向代理vue.js2.6+Tornado5.1.1,使用supervisor统一管理服务
  6. ASP.NET Core 6框架揭秘实例演示[31]:路由&amp;ldquo;高阶&amp;rdquo;用法
  7. MMDetection 使用示例:从入门到出门
  8. NodeJS &amp; Dapr Javascript SDK 官方使用指南
  9. gitpod.io,云端开发调试工具。
  10. Python逆向爬虫之pyquery,非常详细