Java協(xié)程的發(fā)展歷程可以概括為以下幾個(gè)階段:
早期嘗試: 在 Java 早期版本中,并發(fā)主要通過(guò)線程和同步機(jī)制來(lái)實(shí)現(xiàn)。盡管 Java 提供了多線程支持,但由于線程的創(chuàng)建和切換開銷較大,這使得高并發(fā)的場(chǎng)景處理效率較低。
Quasar(2011年): Quasar 是由 Parallel Universe 開發(fā)的一個(gè)基于字節(jié)碼操縱和 bytecode instrumentation 的 Java 協(xié)程庫(kù)。它在 Java 中實(shí)現(xiàn)了類似協(xié)程的概念,通過(guò)操縱字節(jié)碼來(lái)實(shí)現(xiàn)輕量級(jí)的協(xié)程和任務(wù)切換。Quasar 提供了協(xié)程式的編程方式,允許在一個(gè)線程中執(zhí)行多個(gè)協(xié)程,從而避免了線程切換的開銷。
Kotlin Coroutines(2017年): Kotlin 是一種運(yùn)行在 JVM 上的編程語(yǔ)言,由 JetBrains 開發(fā)。Kotlin Coroutines 是 Kotlin 的異步編程框架,允許以協(xié)程的方式編寫異步代碼。雖然 Kotlin 是一種獨(dú)立的編程語(yǔ)言,但它可以與 Java 無(wú)縫集成,因此你可以在 Java 項(xiàng)目中使用 Kotlin Coroutines。
Project Loom(進(jìn)行中): Project Loom 是 OpenJDK 的一個(gè)子項(xiàng)目,致力于為 Java 引入輕量級(jí)線程(稱為 Virtual Threads 或者 Loom Threads)。Loom 的目標(biāo)是在不改變現(xiàn)有 Java 程序的前提下,為 Java 增加纖程的能力。Loom 的設(shè)計(jì)目標(biāo)是實(shí)現(xiàn)一個(gè)高效且易用的協(xié)程和輕量級(jí)線程模型,以解決 Java 并發(fā)編程的挑戰(zhàn)。
Java 標(biāo)準(zhǔn)庫(kù)中仍然沒(méi)有原生支持協(xié)程的特性。然而,上述項(xiàng)目和庫(kù)的出現(xiàn)表明 Java 社區(qū)對(duì)于高效并發(fā)編程的需求,以及對(duì)于協(xié)程式編程的探索和實(shí)踐,并且未來(lái) Java 的發(fā)展可能會(huì)進(jìn)一步引入更加高級(jí)的并發(fā)機(jī)制,為開發(fā)者提供更優(yōu)雅和高效的并發(fā)編程體驗(yàn)。
Java Project Loom是Java語(yǔ)言的一個(gè)重要項(xiàng)目,它旨在改進(jìn)Java虛擬機(jī)(JVM)的執(zhí)行模型,以支持輕量級(jí)線程(Lightweight Threads),從而提高Java在處理并發(fā)和并行編程方面的性能和可伸縮性。本文將介紹Java Project Loom的背景、目標(biāo)、主要特性以及對(duì)Java開發(fā)者和應(yīng)用程序的影響。
在Java開發(fā)中,線程(Thread)是一種常用的并發(fā)機(jī)制,允許程序以多個(gè)獨(dú)立的執(zhí)行路徑同時(shí)運(yùn)行。然而,傳統(tǒng)的Java線程模型存在一些問(wèn)題。每個(gè)線程都映射到操作系統(tǒng)的本地線程,這會(huì)導(dǎo)致創(chuàng)建和銷毀線程的開銷較大。而且,由于每個(gè)線程都會(huì)占用一定的內(nèi)存空間,當(dāng)并發(fā)程度較高時(shí),大量線程的創(chuàng)建可能會(huì)導(dǎo)致內(nèi)存消耗過(guò)大,甚至導(dǎo)致系統(tǒng)崩潰。
為了解決這些問(wèn)題,Java Project Loom項(xiàng)目應(yīng)運(yùn)而生。
Java Project Loom的主要目標(biāo)是引入一種輕量級(jí)線程實(shí)現(xiàn),稱為“Fibers”(纖程),以優(yōu)化Java線程的管理和執(zhí)行模型。Fibers是一種用戶態(tài)線程,由Java虛擬機(jī)(JVM)和運(yùn)行時(shí)系統(tǒng)進(jìn)行管理,不再需要映射到操作系統(tǒng)的本地線程。這樣,F(xiàn)ibers的創(chuàng)建和銷毀開銷將大大降低,并且可以在同一個(gè)操作系統(tǒng)線程內(nèi)運(yùn)行大量Fibers,從而減少內(nèi)存消耗和提高性能。
Java Project Loom帶來(lái)了許多重要特性,其中最顯著的是:
Fibers是Java Project Loom的核心特性。它們是一種輕量級(jí)的、用戶態(tài)的線程實(shí)現(xiàn),可以通過(guò)Fiber API進(jìn)行創(chuàng)建、掛起、恢復(fù)和取消。與傳統(tǒng)線程相比,F(xiàn)ibers的創(chuàng)建和銷毀成本較低,并且可以高效地復(fù)用線程資源,使得應(yīng)用程序可以擁有數(shù)千甚至數(shù)百萬(wàn)個(gè)并發(fā)執(zhí)行的Fibers,而不會(huì)產(chǎn)生顯著的內(nèi)存開銷。
為了支持Fibers,Java Project Loom引入了Continuations的概念。Continuations允許在Fiber被掛起時(shí)保存其執(zhí)行狀態(tài),并在需要時(shí)恢復(fù)到掛起的狀態(tài)。這為Fibers的掛起和恢復(fù)提供了一種高效的機(jī)制,避免了傳統(tǒng)線程上下文切換的開銷。
Java Project Loom還引入了Virtual Threads的概念,它是一種對(duì)Fibers進(jìn)行透明封裝的機(jī)制。Virtual Threads可以根據(jù)應(yīng)用程序的需求來(lái)動(dòng)態(tài)地創(chuàng)建和管理Fibers,讓開發(fā)者可以使用簡(jiǎn)單的編程模型處理大規(guī)模并發(fā)而無(wú)需擔(dān)心線程管理細(xì)節(jié)。
Scoped Threads是Java Project Loom的另一個(gè)重要特性,它允許Fibers在有限的作用域內(nèi)運(yùn)行。這樣,F(xiàn)iber在超出其作用域后將自動(dòng)被銷毀,從而避免了資源泄漏和線程管理的復(fù)雜性。
Java Project Loom的推出將對(duì)Java開發(fā)者和應(yīng)用程序產(chǎn)生深遠(yuǎn)的影響:
通過(guò)引入輕量級(jí)的Fibers,Java Project Loom將使得Java應(yīng)用程序可以更高效地處理大量并發(fā)任務(wù),從而提供更高的并發(fā)性能和更好的可伸縮性。
由于Fibers不再需要映射到操作系統(tǒng)的本地線程,Java應(yīng)用程序的內(nèi)存消耗將顯著降低,特別是在高并發(fā)場(chǎng)景下,這將對(duì)資源有限的環(huán)境和云計(jì)算平臺(tái)尤為重要。
Virtual Threads和Scoped Threads的引入將簡(jiǎn)化并發(fā)編程的代碼邏輯,使得開發(fā)者可以更專注于業(yè)務(wù)邏輯而無(wú)需過(guò)多關(guān)注底層線程管理。
Java Project Loom的改進(jìn)將使得Java應(yīng)用程序更具響應(yīng)性,特別是在高負(fù)載和高并發(fā)情況下,應(yīng)用程序仍然能夠快速響應(yīng)用戶請(qǐng)求。
總體而言,Java Project Loom是Java語(yǔ)言邁向更高并發(fā)性和更好性能的重要一步。通過(guò)引入Fibers和相關(guān)的特性,它將為Java開發(fā)者帶來(lái)更強(qiáng)大的工具,使得開發(fā)高效、高并發(fā)的Java應(yīng)用程序變得更加容易。隨著Java生態(tài)系統(tǒng)的不斷發(fā)展,Java Project Loom必將成為Java開發(fā)中不可或缺的重要組成部分。
許多應(yīng)用程序不會(huì)直接使用 Thread API,而是使用
java.util.concurrent.ExecutorService和 Executors API。Executors API 已更新為 ExecutorServices 的新工廠方法,為每個(gè)任務(wù)啟動(dòng)一個(gè)新線程。虛擬線程足夠便宜,可以為每個(gè)任務(wù)創(chuàng)建一個(gè)新的虛擬線程,永遠(yuǎn)不需要池化虛擬線程。
下面啟動(dòng)一個(gè)虛擬線程來(lái)打印消息。它調(diào)用join方法來(lái)等待線程終止。
Thread thread = Thread.ofVirtual().start(() -> System.out.println("Hello"));thread.join();
下面是一個(gè)在休眠后啟動(dòng)虛擬線程將元素放入隊(duì)列的示例。主線程阻塞在隊(duì)列上,等待元素。
var queue = new SynchronousQueue<String>();Thread.ofVirtual().start(() -> { try { Thread.sleep(Duration.ofSeconds(2)); queue.put("done"); } catch (InterruptedException e) { }}); String msg = queue.take();
Thread.Builder API 也可用于創(chuàng)建 ThreadFactory。以下代碼片段創(chuàng)建的 ThreadFactory 將創(chuàng)建名為“worker-0”、“worker-1”、“worker-2”等的虛擬線程。
ThreadFactory factory = Thread.ofVirtual().name("worker", 0).factory();
以下示例使用 Executors API 創(chuàng)建一個(gè) ExecutorService,為每個(gè)任務(wù)啟動(dòng)一個(gè)新的虛擬線程。 該示例使用 try-with-resources 構(gòu)造來(lái)確保 ExecutorService 在繼續(xù)之前已終止。
ExecutorService定義了提交方法來(lái)執(zhí)行任務(wù)。提交方法不會(huì)阻塞,而是返回一個(gè)可用于等待結(jié)果或異常的 Future 對(duì)象。接受任務(wù)集合的 Submit 方法會(huì)返回一個(gè) Stream,該 Stream 會(huì)延遲填充代表結(jié)果的已完成的 Future 對(duì)象。
該示例還使用 invokeAll 和invokeAny 組合器方法 來(lái)執(zhí)行多個(gè)任務(wù)并等待它們完成。
try (ExecutorService executor = Executors.newVirtualThreadExecutor()) { // Submits a value-returning task and waits for the result Future<String> future = executor.submit(() -> "foo"); String result = future.join(); // Submits two value-returning tasks to get a Stream that is lazily populated // with completed Future objects as the tasks complete Stream<Future<String>> stream = executor.submit(List.of(() -> "foo", () -> "bar")); stream.filter(Future::isCompletedNormally) .map(Future::join) .forEach(System.out::println); // Executes two value-returning tasks, waiting for both to complete List<Future<String>> results1 = executor.invokeAll(List.of(() -> "foo", () -> "bar")); // Executes two value-returning tasks, waiting for both to complete. If one of the // tasks completes with an exception, the other is cancelled. List<Future<String>> results2 = executor.invokeAll(List.of(() -> "foo", () -> "bar"), /*waitAll*/ false); // Executes two value-returning tasks, returning the result of the first to // complete, cancelling the other. String first = executor.invokeAny(List.of(() -> "foo", () -> "bar"));}
Java Project Loom旨在改進(jìn)Java虛擬機(jī)的執(zhí)行模型,其中核心概念是Fibers,也稱為輕量級(jí)線程。Fibers提供了一種輕量級(jí)的線程模型,可以高效地創(chuàng)建和管理大量的并發(fā)任務(wù),而不像傳統(tǒng)線程那樣消耗大量的系統(tǒng)資源。雖然Spring Boot本身沒(méi)有集成Project Loom,但可以在Spring Boot應(yīng)用程序中使用Project Loom來(lái)實(shí)現(xiàn)協(xié)程。為此,你需要使用Java 17或更新版本,并引入Project Loom的依賴。
以下是一個(gè)簡(jiǎn)單的示例,展示如何使用Project Loom的Fibers來(lái)實(shí)現(xiàn)協(xié)程:
public class CoroutineExample { public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newVirtualThreadExecutor(); SubmissionPublisher<String> publisher = new SubmissionPublisher<>(executorService, 1); // Subscribe to the publisher publisher.subscribe(new SimpleSubscriber()); // Publish some data for (int i = 0; i < 5; i++) { publisher.submit("Data " + i); } // Close the publisher and wait for the subscribers to finish publisher.close(); executorService.awaitTermination(1, TimeUnit.SECONDS); executorService.shutdown(); }}
Quasar是一個(gè)基于Java的協(xié)程庫(kù),它提供了協(xié)程的實(shí)現(xiàn)和管理。使用Quasar,你可以在Spring Boot應(yīng)用程序中創(chuàng)建協(xié)程來(lái)處理并發(fā)任務(wù)。
要使用Quasar,你需要將其作為依賴項(xiàng)添加到Spring Boot項(xiàng)目中。然后,你可以使用Quasar提供的API來(lái)創(chuàng)建、掛起和恢復(fù)協(xié)程。
以下是一個(gè)簡(jiǎn)單的示例,展示如何在Spring Boot應(yīng)用程序中使用Quasar實(shí)現(xiàn)協(xié)程:
@FiberSpringBootApplication public class CoroutineExample { public static void main(String[] args) throws InterruptedException { new Fiber<Void>(() -> { for (int i = 0; i < 5; i++) { System.out.println("Data " + i); try { Fiber.sleep(1000); } catch (SuspendExecution | InterruptedException e) { e.printStackTrace(); } } }).start().join(); } }
Vert.x是一個(gè)基于事件驅(qū)動(dòng)的響應(yīng)式框架,它可以讓開發(fā)者使用Java或其他JVM語(yǔ)言編寫高性能的異步應(yīng)用。Vert.x已經(jīng)開始嘗試集成Java虛擬線程,目前有一個(gè)虛擬線程孵化器項(xiàng)目,它包含了一個(gè)async/await的實(shí)現(xiàn)。這個(gè)項(xiàng)目可以讓開發(fā)者使用類似于JavaScript或C#的語(yǔ)法來(lái)編寫異步代碼,而不需要使用回調(diào)或者Future。
Vert.x是一個(gè)用于構(gòu)建響應(yīng)式、高性能、可伸縮的應(yīng)用程序的工具包和框架。它基于Java語(yǔ)言,提供了一個(gè)異步編程模型,使得開發(fā)者可以輕松地構(gòu)建事件驅(qū)動(dòng)的、非阻塞的應(yīng)用程序。
主要特點(diǎn)和優(yōu)勢(shì):
Vert.x適用于構(gòu)建各種類型的應(yīng)用程序,特別是需要高性能、高并發(fā)和實(shí)時(shí)性的場(chǎng)景。它可以用于構(gòu)建Web應(yīng)用程序、API服務(wù)、實(shí)時(shí)通信應(yīng)用、IoT應(yīng)用等。如果您對(duì)響應(yīng)式編程和高性能的應(yīng)用程序開發(fā)感興趣,Vert.x值得一試。
Jetty是一個(gè)輕量級(jí)的Java web服務(wù)器和servlet容器。Jetty也已經(jīng)支持了Java虛擬線程。
Java 19 中引入的虛擬線程在 Jetty 12 中受支持,因?yàn)樗鼈兎謩e從 10.11.10 和 0.12.11 開始在 Jetty 0 和 Jetty 12 中得到支持。
當(dāng) JVM 支持虛擬線程并在 Jetty 中啟用時(shí)(請(qǐng)參閱嵌入式用法和獨(dú)立用法),將使用虛擬線程調(diào)用應(yīng)用程序,這允許它們使用簡(jiǎn)單的阻塞 API,但具有虛擬線程的可伸縮性優(yōu)勢(shì)。
Tomcat是一個(gè)廣泛使用的Java web服務(wù)器和servlet容器。Tomcat也支持Java虛擬線程,并在版本中有相關(guān)說(shuō)明。
Helidon是一個(gè)微服務(wù)框架,它提供了兩種編程模型:Helidon SE和Helidon MP。Helidon SE是一個(gè)基于函數(shù)式編程的輕量級(jí)框架,它支持Reactive Streams和非阻塞IO。Helidon MP是一個(gè)基于標(biāo)準(zhǔn)化的注解驅(qū)動(dòng)的框架,它支持MicroProfile API。Helidon也已經(jīng)集成了Java虛擬線程,并提供了一些示例代碼來(lái)展示如何使用它。
Quarkus是一個(gè)為云原生應(yīng)用而生的全棧框架,它提供了高性能、低內(nèi)存占用、快速啟動(dòng)和熱重載等特性。Quarkus也已經(jīng)支持了Java虛擬線程,并提供了一些文檔和指南來(lái)介紹如何使用它。
本文鏈接:http://www.tebozhan.com/showinfo-26-13359-0.html超越傳統(tǒng)線程:探索Java Loom協(xié)程(纖程/虛擬線程)的無(wú)限潛力
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com
上一篇: Java遍歷一個(gè) List 有哪些方式?每種的實(shí)現(xiàn)原理以及哪種最高效?
下一篇: 讓CSS官方后悔的一些決定