SpringBoot開啟虛擬線程的實(shí)現(xiàn)流程
引言
虛擬線程(Virtual Thread)也稱協(xié)程或纖程,是一種輕量級(jí)的線程實(shí)現(xiàn),與傳統(tǒng)的線程以及操作系統(tǒng)級(jí)別的線程(也稱為平臺(tái)線程)相比,它的創(chuàng)建開銷更小、資源利用率更高,是 Java 并發(fā)編程領(lǐng)域的一項(xiàng)重要?jiǎng)?chuàng)新。
PS:虛擬線程正式發(fā)布于 Java 長(zhǎng)期支持版(Long Term Suort,LTS)Java 21(也就是 JDK 21)。
虛擬線程是一種在 Java 虛擬機(jī)(JVM)層面實(shí)現(xiàn)的邏輯線程,不直接和操作系統(tǒng)的物理線程一一對(duì)應(yīng),因此它可以減少上下文切換所帶來(lái)的性能開銷。
操作系統(tǒng)線程、普通線程(Java 線程)和虛擬線程的關(guān)系如下:
1.虛擬線程使用
虛擬線程的創(chuàng)建有以下 4 種方式:
- Thread.startVirtualThread(Runnable task)
- Thread.ofVirtual().unstarted(Runnable task)
- Thread.ofVirtual().factory()
- Executors.newVirtualThreadPerTaskExecutor()
具體使用如下。
1.1 startVirtualThread
創(chuàng)建虛擬線程,并直接啟動(dòng)執(zhí)行任務(wù):
// 創(chuàng)建并啟動(dòng)虛擬線程 Thread.startVirtualThread(() -> { System.out.println("Do virtual thread."); });
1.2 unstarted
只創(chuàng)建虛擬線程,但不直接啟動(dòng)(創(chuàng)建之后通過(guò) start 啟動(dòng)):
// 創(chuàng)建虛擬線程 Thread vt = Thread.ofVirtual().unstarted(()->{ System.out.println("Do virtual thread."); }); // 運(yùn)行虛擬線程 vt.start();
1.3 factory
先創(chuàng)建虛擬線程工廠,然后再使用工廠創(chuàng)建虛擬線程,之后再調(diào)用 start() 方法進(jìn)行執(zhí)行:
// 創(chuàng)建虛擬線程工廠 ThreadFactory tf = Thread.ofVirtual().factory(); // 創(chuàng)建虛擬線程 Thread vt = tf.newThread(()->{ System.out.println("Do virtual thread."); }); // 運(yùn)行虛擬線程 vt.start();
1.4 newVirtualThreadPerTaskExecutor
創(chuàng)建虛擬線程池:
// 創(chuàng)建一個(gè)支持虛擬線程的線程池 ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); executor.submit(()->{ System.out.println("Do virtual thread."); });
2.虛擬線程 VS 普通線程
虛擬線程和普通線程的區(qū)別主要體現(xiàn)在以下幾點(diǎn):
- 普通線程是和操作系統(tǒng)的物理線程是一一對(duì)應(yīng)的,而虛擬線程是 JVM 層面的邏輯線程,并不和操作系統(tǒng)的物理線程一一對(duì)應(yīng),它可以看作是輕量級(jí)的線程。
- 普通線程默認(rèn)創(chuàng)建的是用戶線程(而守護(hù)線程),而虛擬線程是守護(hù)線程,并且其守護(hù)線程的屬性不能被修改,如果修改就會(huì)報(bào)錯(cuò),如下圖所示:
- 虛擬線程由 JVM 調(diào)度和使用,避免了普通線程頻繁切換的性能開銷,所以相比于普通的線程來(lái)說(shuō),運(yùn)行效率更高。
3.SpringBoot開啟虛擬線程
以最新版的 Spring Boot 3.x 為例,我們開啟虛擬線程很簡(jiǎn)單,只需要在 Spring Boot 配置文件中設(shè)置“spring.threads.virtual.enabled”為“true”即可開啟,以 application.yml 為例,啟用虛擬線程配置如下:
spring: threads: virtual: enabled: true # 啟用虛擬線程
這樣 Spinrg Boot 在啟動(dòng) Tomcat 容器時(shí),會(huì)使用一個(gè)虛擬線程執(zhí)行器來(lái)代表原有的平臺(tái)線程池。
PS:這里是虛擬線程執(zhí)行器,不是虛擬線程池。
如果以上配置未生效的話,還可以通過(guò)修改 Tomcat 配置類,讓其使用虛擬線程來(lái)處理每一個(gè)請(qǐng)求,配置代碼如下:
import java.util.concurrent.Executors; import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatConfiguration { @Bean public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() { return protocolHandler -> { // 使用虛擬線程來(lái)處理每一個(gè)請(qǐng)求 protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor()); }; } }
4.異步任務(wù)開啟虛擬線程
如果你想為 Spring Boot 中的異步任務(wù) @Async 也配置虛擬線程的話,可以在 AsyncConfigurer 配置類中設(shè)置,配置代碼如下:
import java.util.concurrent.Executor; import java.util.concurrent.Executors; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.support.TaskExecutorAdapter; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; @Configuration @EnableAsync // 開啟異步任務(wù) public class AsyncTaskConfiguration implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { return new TaskExecutorAdapter(Executors.newThreadPerTaskExecutor(Thread.ofVirtual().name("virtual-async#", 1).factory())); } }
最后
到此這篇關(guān)于SpringBoot開啟虛擬線程的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)SpringBoot虛擬線程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot Logback日志記錄到數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法
這篇文章主要介紹了SpringBoot Logback日志記錄到數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11基于Java制作一個(gè)簡(jiǎn)易的遠(yuǎn)控終端
這篇文章主要為大家詳細(xì)介紹了如何基于Java制作一個(gè)簡(jiǎn)易的遠(yuǎn)控終端,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的可以了解一下2023-04-04Java幾個(gè)實(shí)例帶你進(jìn)階升華下篇
與其明天開始,不如現(xiàn)在行動(dòng),本文為你帶來(lái)幾個(gè)Java書寫的實(shí)際案例,對(duì)鞏固編程的基礎(chǔ)能力很有幫助,快來(lái)一起往下看看吧2022-03-03SpringBoot多數(shù)據(jù)源讀寫分離的自定義配置問(wèn)題及解決方法
這篇文章主要介紹了SpringBoot多數(shù)據(jù)源讀寫分離的自定義配置,我們可以通過(guò)自定義配置數(shù)據(jù)庫(kù)配置類來(lái)解決這個(gè)問(wèn)題,方式有很多,不同的業(yè)務(wù)采用的方式也不同,下面我簡(jiǎn)單的介紹我們項(xiàng)目的使用的方法2022-06-06Jenkin郵件收發(fā)實(shí)現(xiàn)原理及過(guò)程詳解
這篇文章主要介紹了Jenkin郵件收發(fā)實(shí)現(xiàn)原理及過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09