JDK21的虛擬執行緒是什麼?和平臺執行緒什麼關係?

2023-10-17 18:00:23

虛擬執行緒(Virtual Thread)是 JDK 而不是 OS 實現的輕量級執行緒(Lightweight Process,LWP),由 JVM 排程。許多虛擬執行緒共用同一個作業系統執行緒,虛擬執行緒的數量可以遠大於作業系統執行緒的數量。

在引入虛擬執行緒之前,java.lang.Thread 包已經支援所謂的平臺執行緒,也就是沒有虛擬執行緒之前,我們一直使用的執行緒。JVM 排程程式通過平臺執行緒(載體執行緒)來管理虛擬執行緒,一個平臺執行緒可以在不同的時間執行不同的虛擬執行緒(多個虛擬執行緒掛載在一個平臺執行緒上),當虛擬執行緒被阻塞或等待時,平臺執行緒可以切換到執行另一個虛擬執行緒。

虛擬執行緒、平臺執行緒和系統核心執行緒的關係圖如下所示(圖源:How to Use Java 19 Virtual Threads):

關於平臺執行緒和系統核心執行緒的對應關係多提一點:在 Windows 和 Linux 等主流作業系統中,Java 執行緒採用的是一對一的執行緒模型,也就是一個平臺執行緒對應一個系統核心執行緒。Solaris 系統是一個特例,HotSpot VM 在 Solaris 上支援多對多和一對一。具體可以參考 R 大的回答: JVM 中的執行緒模型是使用者級的麼?

相比較於平臺執行緒來說,虛擬執行緒是廉價且輕量級的,使用完後立即被銷燬,因此它們不需要被重用或池化,每個任務可以有自己專屬的虛擬執行緒來執行。虛擬執行緒暫停和恢復來實現執行緒之間的切換,避免了上下文切換的額外耗費,兼顧了多執行緒的優點,簡化了高並行程式的複雜,可以有效減少編寫、維護和觀察高吞吐量並行應用程式的工作量。

虛擬執行緒在其他多執行緒語言中已經被證實是十分有用的,比如 Go 中的 Goroutine、Erlang 中的程序。

知乎有一個關於 Java 19 虛擬執行緒的討論,感興趣的可以去看看:https://www.zhihu.com/question/536743167

Java 虛擬執行緒的詳細解讀和原理可以看下面這幾篇文章:

虛擬執行緒在 Java 19 中進行了第一次預覽,由JEP 425提出。JDK 20 中是第二次預覽,做了一些細微變化,這裡就不細提了。

最後,我們來看一下四種建立虛擬執行緒的方法:

// 1、通過 Thread.ofVirtual() 建立
Runnable fn = () -> {
  // your code here
};

Thread thread = Thread.ofVirtual(fn)
                      .start();

// 2、通過 Thread.startVirtualThread() 、建立
Thread thread = Thread.startVirtualThread(() -> {
  // your code here
});

// 3、通過 Executors.newVirtualThreadPerTaskExecutor() 建立
var executorService = Executors.newVirtualThreadPerTaskExecutor();

executorService.submit(() -> {
  // your code here
});

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

//4、通過 ThreadFactory 建立
CustomThread customThread = new CustomThread();
// 獲取執行緒工廠類
ThreadFactory factory = Thread.ofVirtual().factory();
// 建立虛擬執行緒
Thread thread = factory.newThread(customThread);
// 啟動執行緒
thread.start(); 

通過上述列舉的 4 種建立虛擬執行緒的方式可以看出,官方為了降低虛擬執行緒的門檻,盡力複用原有的 Thread 執行緒類,這樣可以平滑的過渡到虛擬執行緒的使用。

本文已收錄今 JavaGuide (「Java學習 + 面試指南」一份涵蓋大部分 Java 程式設計師所需要掌握的核心知識)