抱歉,您的瀏覽器無法訪問本站
本頁面需要瀏覽器支持(啟用)JavaScript
了解詳情 >

前言

在2022年9月20日Java19发布啦,再次新增了几个特性,其中最吸引我的就是virtual Thread虚拟线程了,官方提供了虚拟线程的预览,这是Project Loom 的主要成果。

image-20221026155259895

虚拟线程是为了提高Java并发变成的可扩展性,是一种轻量级线程。它并不是为了替代原先的Thread线程,而是一种扩展,类似于Go语言中的协程,可以避免线程的上下文切换所带来的额外消耗。

在原先的线程模型中,每个Java线程都对应一个操作系统的线程,但virtual Thread则可以将多个虚拟线程对应到一个操作系统线程上去。

基本使用

创建虚拟线程

VirtualThread继承于Thread,因此API是互相兼容的。Thread类提供了两个工程方法来创建平台线程和虚拟线程。

  • ofPlatform:创建平台线程
  • ofVirtual:创建虚拟线程
1
Thread thread = Thread.ofVirtual().name("duke").unstarted(runnable);

上面的代码创建了一个线程名为duke的线程,但并没有启动,可以通过start方法来启动。

或者我们直接使用Thread.startVirtualThread(Runnable)方法来创建并启动虚拟线程

判断是否为虚拟线程

官方还提供了Thread.isVirtual()方法来判断该线程是否为虚拟线程。

虚拟线程总为守护线程

虚拟线程总为守护线程,并不会受Thread.SetDaemon方法的影响,这意味这如果没有平台线程在运行的话,程序会直接退出。

虚拟线程总是固定优先级

在目前发布的JDK19的版本中,虚拟线程总是为Thread.NORM_PRIORITY固定优先级,并不会受Thread.setPriority方法的影响。

不支持部分Thread的方法

虚拟线程并不支持 stopsuspendresume 等线程调度方法,当在虚拟线程上运行会抛出异常。

支持虚拟线程线程池(不推荐)

官方也提供了虚拟线程池的相关API,不过官方并不推荐将虚拟线程池化。这是因为虚拟线程的创建并不会消耗很多资源,它是轻量级的,应该为每一个请求都创建一个新的虚拟线程,这样也可以避免一些线程安全的问题。

1
2
3
4
5
6
7
8
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
} // executor.close() is called implicitly, and waits
关于性能

根据官方的说法,虚拟线程可以减少线程的上下文切换,以提升并发效率。

查看网上的数据对比貌似也确实如此,但也同样有使用虚拟线程反而执行速度变慢的问题。

参考资料