看起來Java 21將對(duì)Node JS構(gòu)成強(qiáng)大的挑戰(zhàn)!Java 21中有兩個(gè)巨大的性能增強(qiáng),它們解決了Java經(jīng)常被批評(píng)的兩個(gè)領(lǐng)域:線程和阻塞IO和GC。
Java 21的主要亮點(diǎn):
l Loom項(xiàng)目和虛擬線程
l ZGC(升級(jí)版)
1.虛擬線程
在最長(zhǎng)的一段時(shí)間里,我們研究了非阻塞IO、異步操作,然后是Promises和async/Await來協(xié)調(diào)異步操作。因此,我們不得不處理回調(diào),并執(zhí)行Promises.all()或CompletableFuture.thenComposite()之類的操作來連接幾個(gè)異步操作并處理結(jié)果。
最近,Reactive框架開始將任務(wù)“組合”為功能管道,然后在線程池或執(zhí)行器上運(yùn)行它們。反應(yīng)式函數(shù)式編程比“回調(diào)地獄”要好得多,因此,我們被迫轉(zhuǎn)向函數(shù)式編程模型,以便以優(yōu)雅的方式完成非阻塞/異步。
虛擬線程正在終結(jié)回調(diào)和承諾。Java團(tuán)隊(duì)已經(jīng)成功地用極為廉價(jià)的虛擬線程提供了一種幾乎可以替代線程的方法。因此,即使您執(zhí)行舊的Thread.sleep(5000),虛擬線程也會(huì)分離而不是阻塞。就數(shù)量而言,一臺(tái)普通筆記本電腦可以處理2000到5000個(gè)線程,而同一臺(tái)機(jī)器可以處理100多萬個(gè)虛擬線程。事實(shí)上,官方建議避免使用虛擬線程池。建議每個(gè)任務(wù)都在新的虛擬線程上運(yùn)行。虛擬線程支持所有功能——睡眠、等待、ThreadLocal、鎖定等。
虛擬線程允許我們只編寫常規(guī)的舊迭代和“看似阻塞”的代碼,并讓Java分離/附加真實(shí)的線程,使其變得無阻塞和高性能。然而,我們?nèi)匀恍枰却?/span>Apache Tomcat和Spring這樣的庫(kù)/框架實(shí)現(xiàn)者將所有內(nèi)容從本機(jī)線程轉(zhuǎn)移到虛擬線程。一旦框架完成轉(zhuǎn)換,所有使用這些升級(jí)框架的Java微服務(wù)/單體都將自動(dòng)成為非阻塞的。
以我們?cè)趹?yīng)用程序中遇到的一些線程池為例——Apache Tomcat NIO有25 - 50個(gè)工作線程。想象一下NIO可以有50,000個(gè)虛擬線程。Apache Camel監(jiān)聽器通常有10-20個(gè)線程。想象一下Camel可以有1000-2000個(gè)虛擬線程。當(dāng)然,不再有帶虛擬線程的線程池了——所以,它們將有無限的1000個(gè)線程。這幾乎為Java中的“線程饑餓”畫上了句號(hào)。
只要升級(jí)到充分利用Java 21的框架/庫(kù),我們所有的Java微服務(wù)都將變得無阻塞,只需使用現(xiàn)有代碼。
(注意:一些操作,如同步的也會(huì)阻塞虛擬線程。然而,如果我們用支持虛擬線程的替代方法來代替它們,比如Lock.lock(),那么虛擬線程將能夠分離并執(zhí)行其他任務(wù),直到獲得鎖。為此,庫(kù)作者需要對(duì)代碼做一點(diǎn)點(diǎn)修改,在某些情況下,項(xiàng)目代碼庫(kù)也需要修改,以獲得虛擬線程的好處。
2.ZGC
ZGC現(xiàn)在支持萬億字節(jié)大小的Java堆,具有永久的亞毫秒級(jí)暫停。沒有重要的警告...它可能會(huì)多使用5-10%的內(nèi)存或慢5-10%的分配速度,但不會(huì)再有停止世界的GC暫停和堆大小限制。
這兩項(xiàng)性能改進(jìn)將共同加強(qiáng)Java在編程語言中的地位。它可能會(huì)暫停節(jié)點(diǎn)JS的上升優(yōu)勢(shì),并在某種程度上反應(yīng)式編程。反應(yīng)式/函數(shù)式編程對(duì)于代碼可讀性和管理大量事件驅(qū)動(dòng)的應(yīng)用程序可能仍然是好的,但是我們不這樣做了需要反應(yīng)式編程不再用Java做非阻塞IO了。