自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java 上進了,JDK21 要來了,并發(fā)編程再也不是噩夢了

商務(wù)辦公
當(dāng)前 Java 中的多線程并發(fā)編程絕對是另我們都非常頭疼的一部分,感覺就是學(xué)起來難啃,用起來難用。但是轉(zhuǎn)頭看看使用其他語言的朋友們,根本就沒有這個煩惱嘛,比如 GoLang,感覺人家用起來就很絲滑呢。

大家好,我是一個即將退役的碼農(nóng)

之前寫過 新項目為什么決定用 JDK 17了,還沒過多久,JDK 21 馬上就出來了,看來 Java 這幾年真的是長進了。

目前 Java 的最新穩(wěn)定版是 JDK 20,但這是個過渡版,JDK21就是 LTS 版的了,也快要發(fā)布了,在今年9月份(也就是2023年9月)就要正式發(fā)布了。

但是,猜都不用猜,你肯定還在用 Java 8 吧!

如果說之前的 JDK17你還覺得沒必要折騰,那 JDK21確實有必要關(guān)注一下了。因為 JDK21 引入了一種新型的并發(fā)編程模式。

當(dāng)前 Java 中的多線程并發(fā)編程絕對是另我們都非常頭疼的一部分,感覺就是學(xué)起來難啃,用起來難用。但是轉(zhuǎn)頭看看使用其他語言的朋友們,根本就沒有這個煩惱嘛,比如 GoLang,感覺人家用起來就很絲滑呢。

JDK21 中就在這方面做了很大的改進,讓Java并發(fā)編程變得更簡單一點,更絲滑一點。確切的說,在 JDK19或JDK20中就有這些改進了。

那具體是什么呢?讓我們來具體來看一下。下面是JDK21的 Feature。

其中Virtual Threads、Scoped Values、Structured Concurrency就是針對多線程并發(fā)編程的幾個功能。我們今天也主要來說一下他們。

虛擬線程(Virtual Threads)

虛擬線程是基于協(xié)程的線程,它們與其他語言中的協(xié)程具有相似之處,但也存在一些不同之處。

虛擬線程是依附于主線程的,如果主線程銷毀了,那虛擬線程也不復(fù)存在。

相同之處:

  1. 虛擬線程和協(xié)程都是輕量級的線程,它們的創(chuàng)建和銷毀的開銷都比傳統(tǒng)的操作系統(tǒng)線程要小。
  2. 虛擬線程和協(xié)程都可以通過暫停和恢復(fù)來實現(xiàn)線程之間的切換,從而避免了線程上下文切換的開銷。
  3. 虛擬線程和協(xié)程都可以使用異步和非阻塞的方式來處理任務(wù),提高應(yīng)用程序的性能和響應(yīng)速度。

不同之處:

  1. 虛擬線程是在 JVM 層面實現(xiàn)的,而協(xié)程則是在語言層面實現(xiàn)的。因此,虛擬線程的實現(xiàn)可以與任何支持 JVM 的語言一起使用,而協(xié)程的實現(xiàn)則需要特定的編程語言支持。
  2. 虛擬線程是一種基于線程的協(xié)程實現(xiàn),因此它們可以使用線程相關(guān)的 API,如 ThreadLocal、Lock 和 Semaphore。而協(xié)程則不依賴于線程,通常需要使用特定的異步編程框架和 API。
  3. 虛擬線程的調(diào)度是由 JVM 管理的,而協(xié)程的調(diào)度是由編程語言或異步編程框架管理的。因此,虛擬線程可以更好地與其他線程進行協(xié)作,而協(xié)程則更適合處理異步任務(wù)。

總的來說,虛擬線程是一種新的線程類型,它可以提高應(yīng)用程序的性能和資源利用率,同時也可以使用傳統(tǒng)線程相關(guān)的 API。虛擬線程與協(xié)程有很多相似之處,但也存在一些不同之處。

虛擬線程確實可以讓多線程編程變得更簡單和更高效。相比于傳統(tǒng)的操作系統(tǒng)線程,虛擬線程的創(chuàng)建和銷毀的開銷更小,線程上下文切換的開銷也更小,因此可以大大減少多線程編程中的資源消耗和性能瓶頸。

使用虛擬線程,開發(fā)者可以像編寫傳統(tǒng)的線程代碼一樣編寫代碼,而無需擔(dān)心線程的數(shù)量和調(diào)度,因為 JVM 會自動管理虛擬線程的數(shù)量和調(diào)度。此外,虛擬線程還支持傳統(tǒng)線程相關(guān)的 API,如 ThreadLocal、Lock 和 Semaphore,這使得開發(fā)者可以更輕松地遷移傳統(tǒng)線程代碼到虛擬線程。

虛擬線程的引入,使得多線程編程變得更加高效、簡單和安全,使得開發(fā)者能夠更加專注于業(yè)務(wù)邏輯,而不必過多地關(guān)注底層的線程管理。

結(jié)構(gòu)化并發(fā)(Structured Concurrency)

結(jié)構(gòu)化并發(fā)是一種編程范式,旨在通過提供結(jié)構(gòu)化和易于遵循的方法來簡化并發(fā)編程。使用結(jié)構(gòu)化并發(fā),開發(fā)人員可以創(chuàng)建更容易理解和調(diào)試的并發(fā)代碼,并且不容易出現(xiàn)競爭條件和其他與并發(fā)有關(guān)的錯誤。在結(jié)構(gòu)化并發(fā)中,所有并發(fā)代碼都被結(jié)構(gòu)化為稱為任務(wù)的定義良好的工作單元。任務(wù)以結(jié)構(gòu)化方式創(chuàng)建、執(zhí)行和完成,任務(wù)的執(zhí)行總是保證在其父任務(wù)完成之前完成。

Structured Concurrency(結(jié)構(gòu)化并發(fā))可以讓多線程編程更加簡單和可靠。在傳統(tǒng)的多線程編程中,線程的啟動、執(zhí)行和結(jié)束是由開發(fā)者手動管理的,因此容易出現(xiàn)線程泄露、死鎖和異常處理不當(dāng)?shù)葐栴}。

使用結(jié)構(gòu)化并發(fā),開發(fā)者可以更加自然地組織并發(fā)任務(wù),使得任務(wù)之間的依賴關(guān)系更加清晰,代碼邏輯更加簡潔。結(jié)構(gòu)化并發(fā)還提供了一些異常處理機制,可以更好地管理并發(fā)任務(wù)中的異常,避免因為異常而導(dǎo)致程序崩潰或數(shù)據(jù)不一致的情況。

除此之外,結(jié)構(gòu)化并發(fā)還可以通過限制并發(fā)任務(wù)的數(shù)量和優(yōu)先級,防止資源競爭和饑餓等問題的發(fā)生。這些特性使得開發(fā)者能夠更加方便地實現(xiàn)高效、可靠的并發(fā)程序,而無需過多關(guān)注底層的線程管理。

作用域值(Scoped Values)

作用域值是JDK 20中的一項功能,允許開發(fā)人員創(chuàng)建作用域限定的值,這些值限定于特定的線程或任務(wù)。作用域值類似于線程本地變量,但是設(shè)計為與虛擬線程和結(jié)構(gòu)化并發(fā)配合使用。它們允許開發(fā)人員以結(jié)構(gòu)化的方式在任務(wù)和虛擬線程之間傳遞值,無需復(fù)雜的同步或鎖定機制。作用域值可用于在應(yīng)用程序的不同部分之間傳遞上下文信息,例如用戶身份驗證或請求特定數(shù)據(jù)。

試驗一下

進行下面的探索之前,你要下載至少 JDK19或者直接下載 JDK20,JDK 20 目前(截止到2023年9月份)是正式發(fā)布的最高版本,如果你用 JDK 19的話,沒辦法體驗到Scoped Values的功能。

或者是直接下載 JDK 21 的 Early-Access Builds(早期訪問版本)。在這個地址下載 「jdk.java.net/21/」,下載對應(yīng)的版…

如果你用的是 IDEA ,那你的IDEA 版本最起碼是2022.3 這個版本或者之后的,否則不支持這么新的 JDK 版本。

如果你用的是 JDK19或者 JDK20的話,要在你的項目設(shè)置中將 language level設(shè)置為19或20的 Preview 級別,否則編譯的時候會提示你無法使用預(yù)覽版的功能,虛擬線程就是預(yù)覽版的功能。

如果你用的是 JDK21的話,將 language level 設(shè)置為 X -Experimental Features,另外,因為 JDK21不屬于正式版本,所以需要到 IDEA 的設(shè)置中(注意是 IDEA 的設(shè)置,不是項目的設(shè)置了),將這個項目的 Target bytecode version手動修改為21,目前可選的最高就是20,也就是JDK20。設(shè)置為21之后,就可以使用 JDK21中的這些功能了。

虛擬線程的例子

我們現(xiàn)在啟動線程是怎么做的呢?

先聲明一個線程類,implements 自 Runnable,并實現(xiàn) run方法。

然后就可以使用這個線程類,然后啟動線程了。

中規(guī)中矩,沒毛病。

有了虛擬線程之后呢,怎么實現(xiàn)呢?

Thread.ofPlatform().name("thread-test").start(new SimpleThread());

下面是幾種使用虛擬線程的方式。

1、直接啟動一個虛擬線程

Thread thread = Thread.startVirtualThread(new SimpleThread());

2、使用 ofVirtual(),builder 方式啟動虛擬線程,可以設(shè)置線程名稱、優(yōu)先級、異常處理等配置

3、使用 Factory 創(chuàng)建線程

4、使用 Executors 方式

結(jié)構(gòu)化編程的例子

想一下下面這個場景,假設(shè)你有三個任務(wù)要同時進行,只要任意一個任務(wù)執(zhí)行完成并返回結(jié)果了,那就可以直接用這個結(jié)果了,其他的兩個任務(wù)就可以停止了。比如說一個天氣服務(wù),通過三個渠道獲取天氣情況,只要有一個渠道返回就可以了。

這種場景下, 在 Java 8 下應(yīng)該怎么做呢,當(dāng)然也可以了。

使用 ExecutorService的invokeAll和invokeAny實現(xiàn),但是會有一些額外的工作,在拿到第一個結(jié)果后,要手動關(guān)閉另外的線程。

而 JDK21中呢,可以用結(jié)構(gòu)化編程實現(xiàn)。

ShutdownOnSuccess捕獲第一個結(jié)果并關(guān)閉任務(wù)范圍以中斷未完成的線程并喚醒調(diào)用線程。 適用于任意子任務(wù)的結(jié)果都可以直接使用,并且無需等待其他未完成任務(wù)的結(jié)果的情況。 它定義了獲取第一個結(jié)果或在所有子任務(wù)失敗時拋出異常的方法

ShutdownOnFailure

執(zhí)行多個任務(wù),只要有一個失敗(出現(xiàn)異?;蚱渌鲃訏伋霎惓G闆r),就停止其他未執(zhí)行完的任務(wù),使用scope.throwIfFailed捕捉并拋出異常。 如果所有任務(wù)均正常,則使用 Feture.get() 或*Feture.resultNow() 獲取結(jié)果

Scoped Values 的例子

我們肯定都用過 ThreadLocal,它是線程本地變量,只要這個線程沒銷毀,可以隨時獲取 ThredLocal 中的變量值。Scoped Values 也可以在線程內(nèi)部隨時獲取變量,只不過它有個作用域的概念,超出作用域就會銷毀。

上面的例子模擬一個用戶登錄的過程,使用 ScopedValue.newInstance()聲明了一個 ScopedValue,用 ScopedValue.where給 ScopedValue設(shè)置值,并且使用 run 方法執(zhí)行接下來要做的事兒,這樣一來,ScopedValue就在 run() 的內(nèi)部隨時可獲取了,在run方法中,模擬調(diào)用了一個service 的login方法,不用傳遞LoginUser這個參數(shù),就可以直接通過LoginUser.get方法獲取當(dāng)前登錄用戶的值了。

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2024-12-24 12:00:00

inlinC++17頭文件

2023-12-28 10:49:27

響應(yīng)式編程異步

2023-10-20 08:12:00

JDK21線程池配置

2023-12-21 09:00:00

開發(fā)并發(fā)編程

2020-01-21 21:15:16

WiFi網(wǎng)絡(luò)WiFi6

2021-12-21 09:05:46

命令Linux敲錯

2024-06-06 16:15:00

2016-02-04 09:17:59

2023-09-26 12:16:29

JDK 21Java

2024-04-15 00:08:00

MySQLInnoDB數(shù)據(jù)庫

2023-09-16 13:30:37

AI訓(xùn)練

2021-01-28 16:58:12

數(shù)字貨幣加密貨幣區(qū)塊鏈

2021-12-01 17:24:11

編程學(xué)習(xí)網(wǎng)站程序員

2024-02-26 00:00:00

Docker容器

2015-05-29 09:01:48

2023-07-29 22:02:06

MyBatis數(shù)據(jù)庫配置

2020-06-15 08:03:17

大文件OOM內(nèi)存

2022-06-01 10:09:39

Linux網(wǎng)絡(luò)延遲

2021-03-26 15:18:11

代碼工具Mockoon

2018-10-11 15:51:32

ChromeGoogle瀏覽器
點贊
收藏

51CTO技術(shù)棧公眾號