科技與狠活?JDK19中的虛擬線程到底什么鬼?
本文給大家介紹了一下JDK 19新推出的虛擬線程,或者叫協程,主要是為了解決在讀書操作系統(tǒng)中線程需要依賴內核線程的實現,導致有很多額外開銷的問題。通過在Java語言層面引入虛擬線程,通過JVM進行調度管理,從而減少上下文切換的成本。
?最近,JDK 19發(fā)布了,推出了幾個新的特性,其中有一個比較值得關注的那就是新增了虛擬線程。
【資料圖】
很多人可能比較疑惑,到底什么是虛擬線程,和我們現在使用的平臺線程有啥區(qū)別呢?
要說清楚JDK 19中的虛擬線程,我們要先來了解一下線程都是怎么實現的。
線程的實現方式
我們都知道,在操作系統(tǒng)中,線程是比進程更輕量級的調度執(zhí)行單位,線程的引入可以把一個進程的資源分配和執(zhí)行調度分開,各個線程既可以共享進程資源,又可以獨立調度。
其實,線程的實現方式主要有三種:分別是使用內核線程實現、使用用戶線程實現以及使用用戶線程加輕量級進程混合實現。
使用內核線程實現
內核線程(Kernel-Level Thread,KLT)就是直接由操作系統(tǒng)內核(Kernel,下稱內核)支持的線程,這種線程由內核來完成線程切換,內核通過操縱調度器(Scheduler)對線程進行調度,并負責將線程的任務映射到各個處理器上,并向應用程序提供API接口來管理線程。
應用程序一般不會直接去使用內核線程,而是去使用內核線程的一種高級接口——輕量級進程(Light Weight Process,LWP),輕量級進程就是我們通常意義上所講的線程,由于每個輕量級進程都由一個內核線程支持,因此只有先支持內核線程,才能有輕量級進程。
有了內核線程的支持,每個輕量級進程都成為一個獨立的調度單元,即使有一個輕量級進程在系統(tǒng)調用中阻塞了,也不會影響整個進程繼續(xù)工作。
但是輕量級進程具有它的局限性:首先,由于是基于內核線程實現的,所以各種線程操作,如創(chuàng)建、析構及同步,都需要進行系統(tǒng)調用。而系統(tǒng)調用的代價相對較高,需要在用戶態(tài)(User Mode)和內核態(tài)(Kernel Mode)中來回切換。其次,每個輕量級進程都需要有一個內核線程的支持,因此輕量級進程要消耗一定的內核資源(如內核線程的??臻g),因此一個系統(tǒng)支持輕量級進程的數量是有限的。
使用用戶線程實現
在用戶空間建立線程庫,通過運行時系統(tǒng)(Run-time System)來完成線程的管理,因為這種線程的實現是在用戶空間的,所以操作系統(tǒng)的內核并不知道線程的存在,所以內核管理的還是進程,所以這種線程的切換不需要內核操作。
這種實現方式下,一個進程和線程之間的關系是一對多的。
這種線程實現方式的優(yōu)點是線程切換快,并且可以運行在任何操作系統(tǒng)之上,只需要實現線程庫就行了。但是缺點也比較明顯,就是所有線程的操作都需要用戶程序自己處理,并且因為大多數系統(tǒng)調用都是阻塞的,所以一旦一個進程阻塞了,那么進程中的所有線程也會被阻塞。還有就是多處理器系統(tǒng)中如何將線程映射到其他處理器上也是一個比較大的問題。
使用用戶線程加輕量級進程混合實現
還有一種混合實現的方式,就是線程的創(chuàng)建在用戶空間完成,通過線程庫進行,但是線程的調度是由內核來完成的。多個用戶線程通過多路復用來復用多個內核線程。這個就不展開講了
Java線程的實現方式
以上講的是操作系統(tǒng)的線程的實現的三種方式,不同的操作系統(tǒng)在實現線程的時候會采用不同的機制,比如windows采用的是內核線程實現的,而Solaris則是通過混合模式實現的。
而Java作為一門跨平臺的編程語言,實際上他的線程的實現其實是依賴具體的操作系統(tǒng)的。而比較常用的windows和linux來說,都是采用內核線程的方式實現的。
也就是說,當我們在JAVA代碼中創(chuàng)建一個Tread的時候,其實是需要映射到操作系統(tǒng)的線程的具體實現的,因為常見的通過內核線程實現的方式在創(chuàng)建、調度時都需要進行內核參與,所以成本比較高,盡管JAVA中提供了線程池的方式來避免重復創(chuàng)建線程,但是依舊有很大的優(yōu)化空間。而且這種實現方式意味著受機器資源的影響,平臺線程數也是有限制的。
虛擬線程
JDK 19引入的虛擬線程,是JDK 實現的輕量級線程,他可以避免上下文切換帶來的的額外耗費。他的實現原理其實是JDK不再是每一個線程都一對一的對應一個操作系統(tǒng)的線程了,而是會將多個虛擬線程映射到少量操作系統(tǒng)線程中,通過有效的調度來避免那些上下文切換。
而且,我們可以在應用程序中創(chuàng)建非常多的虛擬線程,而不依賴于平臺線程的數量。這些虛擬線程是由JVM管理的,因此它們不會增加額外的上下文切換開銷,因為它們作為普通Java對象存儲在RAM中。
虛擬線程與平臺線程的區(qū)別
首先,虛擬線程總是守護線程。setDaemon (false)方法不能將虛擬線程更改為非守護線程。所以,需要注意的是,當所有啟動的非守護進程線程都終止時,JVM將終止。這意味著JVM不會等待虛擬線程完成后才退出。
其次,即使使用setPriority()方法,虛擬線程始終具有normal的優(yōu)先級,且不能更改優(yōu)先級。在虛擬線程上調用此方法沒有效果。
還有就是,虛擬線程是不支持stop()、suspend()或resume()等方法。這些方法在虛擬線程上調用時會拋出UnsupportedOperationException異常。
如何使用虛擬線程
接下來介紹一下,在JDK 19中如何使用虛擬線程。
首先,通過Thread.startVirtualThread()可以運行一個虛擬線程:
Thread.startVirtualThread(() -> { System.out.println("虛擬線程執(zhí)行中...");});
其次,通過Thread.Builder也可以創(chuàng)建虛擬線程,Thread類提供了ofPlatform()來創(chuàng)建一個平臺線程、ofVirtual()來創(chuàng)建虛擬現場。
Thread.Builder platformBuilder = Thread.ofPlatform().name("平臺線程");Thread.Builder virtualBuilder = Thread.ofVirtual().name("虛擬線程");Thread t1 = platformBuilder .start(() -> {...}); Thread t2 = virtualBuilder.start(() -> {...});
另外,線程池也支持了虛擬線程,可以通過Executors.newVirtualThreadPerTaskExecutor()來創(chuàng)建虛擬線程:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { IntStream.range(0, 10000).forEach(i -> { executor.submit(() -> { Thread.sleep(Duration.ofSeconds(1)); return i; }); });}
但是,其實并不建議虛擬線程和線程池一起使用,因為Java線程池的設計是為了避免創(chuàng)建新的操作系統(tǒng)線程的開銷,但是創(chuàng)建虛擬線程的開銷并不大,所以其實沒必要放到線程池中。
性能差異
說了半天,虛擬線程到底能不能提升性能,能提升多少呢?我們來做個測試。
我們寫一個簡單的任務,在控制臺中打印消息之前等待1秒:
final AtomicInteger atomicInteger = new AtomicInteger();Runnable runnable = () -> { try { Thread.sleep(Duration.ofSeconds(1)); } catch(Exception e) { System.out.println(e); } System.out.println("Work Done - " + atomicInteger.incrementAndGet());};
現在,我們將從這個Runnable創(chuàng)建10,000個線程,并使用虛擬線程和平臺線程執(zhí)行它們,以比較兩者的性能。
先來我們比較熟悉的平臺線程的實現:
Instant start = Instant.now();try (var executor = Executors.newFixedThreadPool(100)) { for(int i = 0; i < 10_000; i++) { executor.submit(runnable); }}Instant finish = Instant.now();long timeElapsed = Duration.between(start, finish).toMillis(); System.out.println("總耗時 : " + timeElapsed);
輸出結果為:
總耗時 : 102323
總耗時大概100秒左右。接下來再用虛擬線程跑一下看看
因為在JDK 19中,虛擬線程是一個預覽API,默認是禁用。所以需要使用$ java——source 19——enable-preview xx.java 的方式來運行代碼。?
Instant start = Instant.now();try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { for(int i = 0; i < 10_000; i++) { executor.submit(runnable); }}Instant finish = Instant.now();long timeElapsed = Duration.between(start, finish).toMillis(); System.out.println("總耗時 : " + timeElapsed);
使用 Executors.newVirtualThreadPerTaskExecutor()來創(chuàng)建虛擬線程,執(zhí)行結果如下:
總耗時 : 1674
總耗時大概1.6秒左右。
100秒和1.6秒的差距,足以看出虛擬線程的性能提升還是立竿見影的。
總結
本文給大家介紹了一下JDK 19新推出的虛擬線程,或者叫協程,主要是為了解決在讀書操作系統(tǒng)中線程需要依賴內核線程的實現,導致有很多額外開銷的問題。通過在Java語言層面引入虛擬線程,通過JVM進行調度管理,從而減少上下文切換的成本。
同時我們經過簡單的demo測試,發(fā)現虛擬線程的執(zhí)行確實高效了很多。但是使用的時候也需要注意,虛擬線程是守護線程,所以有可能會沒等他執(zhí)行完虛擬機就會shutdown掉。
參考資料:
https://openjdk.org/jeps/425
https://howtodoinjava.com/java/multi-threading/virtual-threads/
關鍵詞:
相關閱讀
-
科技與狠活?JDK19中的虛擬線程到底什么鬼?
本文給大家介紹了一下JDK19新推出的虛擬線程,或者叫協程,主要是為... -
男子沙漠迷路120小時 民警用無人機成功營救
男子沙漠迷路120小時民警用無人機成功營救,公安局,無人機,尉犁縣,沙漠迷路 -
個稅速算扣除數是什么?速算扣除數怎么...
個稅速算扣除數是什么?速算扣除數是個人所得稅中用來修正個稅計算中... -
二甲氨基乙醇酒石酸氫鹽添加量(二甲氨...
當前大家對于二甲氨基乙醇酒石酸氫鹽都是頗為感興趣的,大家都想要... -
HD Audio 是什么
高清音頻(HDaudio)是指錄制音樂時使用的高帶寬音頻信號。不同的軟件... -
無形資產攤銷年限是什么?怎樣進行無形...
無形資產攤銷年限是什么?無形資產攤銷年限:一般情況下,無形資產攤... -
惡人報喜迅雷下載 1080p 下載_惡人報...
1、后,才趴在他的胸膛上,一邊畫著圈圈一邊說的。2、“我當集團副... -
我不知道我怎么了我還在期待是什么歌-天...
現在許多熱門歌曲都會被作為一段視頻的背景音樂出現,由于都是一小... -
剛漲完價,特斯拉Model S又推出賽道套...
5月6日消息,特斯拉ModelSPlaid將提供新的賽道套件,可以大幅提升車... -
權責發(fā)生制和收付實現制有什么區(qū)別?權...
權責發(fā)生制和收付實現制有什么區(qū)別?1、概念不同:權責發(fā)生制是相對... -
什么是發(fā)票?發(fā)票管理辦法是什么?發(fā)票...
什么是發(fā)票?發(fā)票是指一切單位和個人在購銷商品、提供勞務或接受勞務... -
汽車購置稅怎么算?2023購置稅還會減半嗎?
汽車購置稅怎么算?汽車購置稅計算公式:購置稅=計稅價格×10%(... -
【全球時快訊】紹興數智產業(yè)園正式啟動
4月27日,紹興數智產業(yè)園項目啟動儀式在紹興舉行。首批入園企業(yè)代表... -
每日速遞:從“淄博燒烤”到“青年與海...
辯論賽你來我往,唇槍舌劍,總是閃爍著思辨的智慧。5月3日晚,浙江... -
深入交流 探討糖尿病管理模式創(chuàng)新 —...
點擊藍字關注我們4月15日,梨園社區(qū)衛(wèi)生服務中心主任甘靜雯受邀在第... -
百融智匯云:發(fā)揮“智能路由”優(yōu)勢 助...
近年來,全球經濟發(fā)展中,人工智能、大數據、云計算和區(qū)塊鏈等前沿... -
天天短訊!慢性腸炎吃什么、禁什么呢?
腸炎是細菌、病毒、真菌和寄生蟲等引起的小腸炎和結腸炎。臨床表現... -
市盈率是什么意思?市盈率800倍意味著什么?
市盈率是什么意思?市盈率也稱本益比、股價收益比率或市價盈利比率。... -
cma是什么證書?cma的報考條件和費用是什么?
cma是什么證書?CMA證書是美國注冊管理會計師(Certified Management... -
國內冠軍宣布加入日本聯賽,將與張本智...
周雨也是有一定實力的,雖然已經退役了,但是他和閆安、方博“92一...