Java協(xié)程編程之Loom
Java協(xié)程編程Loom
前提:
OpenJDK給出的官網(wǎng)https://openjdk.java.net/projects/loom有少量Loom項(xiàng)目相關(guān)的信息)JDK17編譯和JDK18編譯等早期版本,Loom早期版本JDK18編譯的版本:下載入口在:https://jdk.java.net/loom
由于該JDK版本過高,目前可以使用主流IDE導(dǎo)入Loom-JDK-18+9進(jìn)行代碼高亮和語法提醒,暫時(shí)找不到方法進(jìn)行編譯,暫時(shí)使用該JDK執(zhí)行目錄下的的javac命令腳本進(jìn)行編譯,使用java命令腳本運(yùn)行。
1、Loom項(xiàng)目簡單介紹
Loom - Fibers, Continuations and Tail-Calls for the JVM
Loom項(xiàng)目的標(biāo)題已經(jīng)凸顯了引入的三大新特性:
Fibers:幾年前看過當(dāng)時(shí)的Loom項(xiàng)目的測試代碼就是使用Fiber這個(gè)API(現(xiàn)在這個(gè)API已經(jīng)被移除),意為輕量級(jí)線程,即協(xié)程,又稱為輕量級(jí)用戶線程,很神奇的是在目前的JDK中實(shí)際上稱為Virtual Thread(虛擬線程)Continuations:直譯為"連續(xù)",實(shí)現(xiàn)上有點(diǎn)像閉包,參考不少資料,尚未準(zhǔn)確理解其具體含義,感覺可以"粗暴"解讀為"程序接下來要執(zhí)行什么"或者"下一個(gè)要執(zhí)行的代碼塊"Tail-Calls:尾調(diào)用VM級(jí)別支持
三個(gè)新特性不詳細(xì)展開,目前只是EA版本,還存在修改的可能性,所以也沒必要詳細(xì)展開。
2、Virtual Thread使用
當(dāng)前版本Loom項(xiàng)目中協(xié)程使用并沒有引入一個(gè)新的公開的虛擬線程VirtualThread類,雖然真的存在VirtualThread,但這個(gè)類使用default修飾符,隱藏在java.lang包中,并且VirtualThread是Thread的子類。協(xié)程的創(chuàng)建API位于Thread類中:

使用此API創(chuàng)建協(xié)程如下:
public static void main(String[] args) {
Thread fiber = Thread.startVirtualThread(() -> System.out.println("Hello Fiber"));
}
從當(dāng)前的源碼可知:
VirtualThread會(huì)通過Thread.currentThread()獲取父線程的調(diào)度器,如果在main方法運(yùn)行,那么上面代碼中的協(xié)程實(shí)例的父線程就是main線程- 默認(rèn)的調(diào)度器為系統(tǒng)創(chuàng)建的
ForkJoinPool實(shí)例(VirtualThread.DEFAULT_SCHEDULER),輸入的Runnable實(shí)例會(huì)被封裝為RunContinuation,最終由調(diào)度器執(zhí)行 - 對(duì)于
timed unpark(正在阻塞,等待喚醒)的協(xié)程,使用系統(tǒng)創(chuàng)建的ScheduledExecutorService實(shí)例進(jìn)行喚醒 - 這個(gè)靜態(tài)工廠方法創(chuàng)建完協(xié)程馬上運(yùn)行,返回的是協(xié)程實(shí)例
如果按照上面的Thread.startVirtualThread()方法去創(chuàng)建協(xié)程,顯然無法定義協(xié)程的名稱等屬性。Loom項(xiàng)目為Thread類引入了建造者模式,比較合理地解決了這個(gè)問題:
// 創(chuàng)建平臺(tái)線程建造器,對(duì)應(yīng)于Thread實(shí)例
public static Builder.OfPlatform ofPlatform() {
return new ThreadBuilders.PlatformThreadBuilder();
}
// 創(chuàng)建虛擬線程建造器,對(duì)應(yīng)于VirtualThread
public static Builder.OfVirtual ofVirtual() {
return new ThreadBuilders.VirtualThreadBuilder();
}
簡單說就是:
ofPlatform()方法用于構(gòu)建Thread實(shí)例,這里的Platform Thread(平臺(tái)線程)其實(shí)就是JDK1.0引入的線程實(shí)例,普通的用戶線程
ofVirtual()方法用于構(gòu)建VirtualThread實(shí)例,也就是構(gòu)建協(xié)程實(shí)例
這兩個(gè)建造器實(shí)例的所有Setter方法鏈展開如下:
public static void main(String[] args) {
Thread.Builder.OfPlatform platformThreadBuilder = Thread.ofPlatform()
// 是否守護(hù)線程
.daemon(true)
// 線程組
.group(Thread.currentThread().getThreadGroup())
// 線程名稱
.name("thread-1")
// 線程名稱前綴 + 起始自增數(shù)字 => prefix + start,下一個(gè)創(chuàng)建的線程名稱就是prefix + (start + 1)
// start > 0的情況下會(huì)覆蓋name屬性配置
.name("thread-", 1L)
// 是否啟用ThreadLocal
.allowSetThreadLocals(false)
// 是否啟用InheritableThreadLocal
.inheritInheritableThreadLocals(false)
// 設(shè)置優(yōu)先級(jí)
.priority(100)
// 設(shè)置線程棧深度
.stackSize(10)
// 設(shè)置未捕獲異常處理器
.uncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
}
});
// thread-1
Thread firstThread = platformThreadBuilder.unstarted(() -> System.out.println("Hello Platform Thread First"));
// thread-2
Thread secondThread = platformThreadBuilder.unstarted(() -> System.out.println("Hello Platform Thread Second"));
Thread.Builder.OfVirtual virtualThreadBuilder = Thread.ofVirtual()
// 協(xié)程名稱
.name("fiber-1")
// 協(xié)程名稱前綴 + 起始自增數(shù)字 => prefix + start,下一個(gè)創(chuàng)建的協(xié)程名稱就是prefix + (start + 1)
// start > 0的情況下會(huì)覆蓋name屬性配置
.name("fiber-", 1L)
// 是否啟用ThreadLocal
.allowSetThreadLocals(false)
// 是否啟用InheritableThreadLocal
.inheritInheritableThreadLocals(false)
// 設(shè)置調(diào)度器,Executor實(shí)例,也就是調(diào)度器是一個(gè)線程池,設(shè)置為NULL會(huì)使用VirtualThread.DEFAULT_SCHEDULER
.scheduler(null)
// 設(shè)置未捕獲異常處理器
.uncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
}
});
// fiber-1
Thread firstFiber = virtualThreadBuilder.unstarted(() -> System.out.println("Hello Platform Virtual First"));
// fiber-2
Thread secondFiber = virtualThreadBuilder.unstarted(() -> System.out.println("Hello Platform Virtual Second"));
}
這里可以發(fā)現(xiàn)一點(diǎn),就是建造器是可以復(fù)用的。如果想用建造器創(chuàng)建同一批參數(shù)設(shè)置相同的線程或者協(xié)程,可以設(shè)置name(String prefix, long start)方法,定義線程或者協(xié)程的名稱前綴和一個(gè)大于等于0的數(shù)字,反復(fù)調(diào)用Builder#unstarted(Runnable task)方法就能批量創(chuàng)建線程或者協(xié)程,名稱就設(shè)置為prefix + start、prefix + (start + 1)、prefix + (start + 2)以此類推。協(xié)程創(chuàng)建基本就是這么簡單,運(yùn)行的話直接調(diào)用start()方法:
public class FiberSample2 {
public static void main(String[] args) throws Exception {
Thread.ofVirtual()
.name("fiber-1")
.allowSetThreadLocals(false)
.inheritInheritableThreadLocals(false)
.unstarted(() -> {
Thread fiber = Thread.currentThread();
System.out.printf("[%s,daemon:%s,virtual:%s] - Hello World\n", fiber.getName(),
fiber.isDaemon(), fiber.isVirtual());
}).start();
// 主線程休眠
Thread.sleep(Long.MAX_VALUE);
}
}
目前無法在主流IDE編譯上面的類,所以只能使用該JDK目錄下的工具編譯和運(yùn)行,具體如下:
# 執(zhí)行 - 當(dāng)前目錄I:\J-Projects\framework-source-code\fiber-sample\src\main\java (1)編譯:I:\Environment\Java\jdk-18-loom\bin\javac.exe I:\J-Projects\framework-source-code\fiber-sample\src\main\java\cn\throwx\fiber\sample\FiberSample2.java (2)執(zhí)行main方法:I:\Environment\Java\jdk-18-loom\bin\java.exe cn.throwx.fiber.sample.FiberSample2
這里也看出了一點(diǎn),所有的協(xié)程實(shí)例的daemon標(biāo)識(shí)默認(rèn)為true且不能修改

以上就是Java協(xié)程編程之Loom的詳細(xì)內(nèi)容,更多關(guān)于Java編程Loom的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺談shiro的SecurityManager類結(jié)構(gòu)
下面小編就為大家?guī)硪黄獪\談shiro的SecurityManager類結(jié)構(gòu)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07
Druid(新版starter)在SpringBoot下的使用教程
Druid是Java語言中最好的數(shù)據(jù)庫連接池,Druid能夠提供強(qiáng)大的監(jiān)控和擴(kuò)展功能,DruidDataSource支持的數(shù)據(jù)庫,這篇文章主要介紹了Druid(新版starter)在SpringBoot下的使用,需要的朋友可以參考下2023-05-05
SpringBoot開發(fā)案例 分布式集群共享Session詳解
這篇文章主要介紹了SpringBoot開發(fā)案例 分布式集群共享Session詳解,在分布式系統(tǒng)中,為了提升系統(tǒng)性能,通常會(huì)對(duì)單體項(xiàng)目進(jìn)行拆分,分解成多個(gè)基于功能的微服務(wù),可能還會(huì)對(duì)單個(gè)微服務(wù)進(jìn)行水平擴(kuò)展,保證服務(wù)高可用,需要的朋友可以參考下2019-07-07
Java使用Graphics2D實(shí)現(xiàn)字符串文本自動(dòng)換行
這篇文章主要為大家詳細(xì)介紹了Java如何使用Graphics2D實(shí)現(xiàn)字符串文本自動(dòng)換行,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
使用Springboot+poi上傳并處理百萬級(jí)數(shù)據(jù)EXCEL
這篇文章主要介紹了使用Springboot+poi上傳并處理百萬級(jí)數(shù)據(jù)EXCEL,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Dependency ‘XXX:‘ not found問題的三步解決
這篇文章主要介紹了Dependency ‘XXX:‘ not found問題的三步解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01

