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

JDK19推出新特性虛擬線程是什么?

開發(fā) 前端
Java虛擬線程相對于傳統(tǒng)線程具有更好的性能表現(xiàn),特別是在高并發(fā)場景下。但是需要注意的是,虛擬線程并不是萬能的,過度使用虛擬線程也可能會導(dǎo)致其他問題,如線程數(shù)量過多、線程間通信和同步問題等。

JDK19推出了幾個新的特性,其中最具有特點的有以下幾個。

圖片圖片

  1. 記錄模式(預(yù)覽版):使用記錄模式增強Java編程語言以解構(gòu)記錄值,可以嵌套記錄模式和類型模式,實現(xiàn)強大的、聲明性的和可組合的數(shù)據(jù)導(dǎo)航和處理形式。這是一個預(yù)覽語言功能。
  2. Linux/RISC-V移植:將JDK移植到Linux/RISC-V,目前僅支持RISC-V的RV64GV配置(包含向量指令的通用64位ISA)。將來可能會考慮支持其他RISC-V配置,例如通用32位配置(RV32G)。
  3. 外部函數(shù)和內(nèi)存API(預(yù)覽版):引入一個API,Java程序可以通過該API與Java運行時之外的代碼和數(shù)據(jù)進行互操作。這是一個預(yù)覽版API。
  4. 虛擬線程(預(yù)覽版):將虛擬線程引入Java平臺。虛擬線程是輕量級線程,可顯著地減少編寫、維護和觀察高吞吐量并發(fā)應(yīng)用程序的工作量。
  5. 結(jié)構(gòu)化并發(fā)(培養(yǎng)階段):旨在通過結(jié)構(gòu)化并發(fā)API簡化多線程編程。這種并發(fā)性將在不同線程中運行的多個任務(wù)視為單個工作單元,以簡化錯誤處理和取消,提高了可靠性和可觀察性。這個特性來自Project Loom,它引入了一個新的輕量級并發(fā)模型。

我們看到其中有一個比較值得關(guān)注的那就是新增了虛擬線程。到底什么是虛擬線程,和我們現(xiàn)在使用的線程有啥區(qū)別呢?

線程的實現(xiàn)方式

在操作系統(tǒng)中,線程是比進程更輕量級的調(diào)度執(zhí)行單位,線程的引入可以把一個進程的資源分配和執(zhí)行調(diào)度分開,各個線程既可以共享進程資源,又可以獨立調(diào)度。

線程的實現(xiàn)方式主要有三種:分別是使用內(nèi)核線程實現(xiàn)、使用用戶線程實現(xiàn)以及使用用戶線程加輕量級進程混合實現(xiàn)。

「使用內(nèi)核線程實現(xiàn)」:內(nèi)核線程(Kernel-Level Thread,KLT)直接由操作系統(tǒng)內(nèi)核支持,由內(nèi)核完成線程切換,內(nèi)核通過操縱調(diào)度器對線程進行調(diào)度,并負(fù)責(zé)將線程的任務(wù)映射到各個處理器上,同時向應(yīng)用程序提供API接口來管理線程。應(yīng)用程序一般不直接使用內(nèi)核線程,而是使用內(nèi)核線程的一種高級接口——輕量級進程(Light Weight Process,LWP)。

應(yīng)用程序一般不會直接去使用內(nèi)核線程,而是去使用內(nèi)核線程的一種高級接口——輕量級進程(Light Weight Process,LWP),輕量級進程就是我們通常意義上所講的線程,由于每個輕量級進程都由一個內(nèi)核線程支持,因此只有先支持內(nèi)核線程,才能有輕量級進程。

有了內(nèi)核線程的支持,每個輕量級進程都成為一個獨立的調(diào)度單元,即使有一個輕量級進程在系統(tǒng)調(diào)用中阻塞了,也不會影響整個進程繼續(xù)工作。

但是輕量級進程具有它的局限性:首先,由于是基于內(nèi)核線程實現(xiàn)的,所以各種線程操作,如創(chuàng)建、析構(gòu)及同步,都需要進行系統(tǒng)調(diào)用。而系統(tǒng)調(diào)用的代價相對較高,需要在用戶態(tài)(User Mode)和內(nèi)核態(tài)(Kernel Mode)中來回切換。其次,每個輕量級進程都需要有一個內(nèi)核線程的支持,因此輕量級進程要消耗一定的內(nèi)核資源(如內(nèi)核線程的??臻g),因此一個系統(tǒng)支持輕量級進程的數(shù)量是有限的。

「使用用戶線程實現(xiàn)」:在用戶空間建立線程庫,通過運行時系統(tǒng)完成線程的管理。這種實現(xiàn)方式下,一個進程和線程之間是一對多的關(guān)系。其優(yōu)點是線程切換快,并且可以運行在任何操作系統(tǒng)之上,只需要實現(xiàn)線程庫即可。

這種實現(xiàn)方式下,一個進程和線程之間的關(guān)系是一對多的。

這種線程實現(xiàn)方式的優(yōu)點是線程切換快,并且可以運行在任何操作系統(tǒng)之上,只需要實現(xiàn)線程庫就行了。但是缺點也比較明顯,就是所有線程的操作都需要用戶程序自己處理,并且因為大多數(shù)系統(tǒng)調(diào)用都是阻塞的,所以一旦一個進程阻塞了,那么進程中的所有線程也會被阻塞。還有就是多處理器系統(tǒng)中如何將線程映射到其他處理器上也是一個比較大的問題。

「使用用戶線程加輕量級進程混合實現(xiàn)」:這種實現(xiàn)方式結(jié)合了上述兩種方式的優(yōu)點,既具有用戶線程實現(xiàn)方式的線程切換快的優(yōu)點,也具有內(nèi)核線程實現(xiàn)方式的操作系統(tǒng)支持性好的優(yōu)點。

「Java線程的實現(xiàn)方式」Java作為一門跨平臺的編程語言,實際上他的線程的實現(xiàn)其實是依賴具體的操作系統(tǒng)的。而比較常用的windows和linux來說,都是采用內(nèi)核線程的方式實現(xiàn)的。也就是說,當(dāng)我們在JAVA代碼中創(chuàng)建一個Thread的時候,其實是需要映射到操作系統(tǒng)的線程的具體實現(xiàn)的,因為常見的通過內(nèi)核線程實現(xiàn)的方式在創(chuàng)建、調(diào)度時都需要進行內(nèi)核參與,所以成本比較高,盡管JAVA中提供了線程池的方式來避免重復(fù)創(chuàng)建線程,但是依舊有很大的優(yōu)化空間。而且這種實現(xiàn)方式意味著受機器資源的影響,平臺線程數(shù)也是有限制的。

虛擬線程

JDK19引入的虛擬線程,虛擬線程是輕量級線程,主要用于實現(xiàn)高吞吐量的并發(fā)應(yīng)用程序。與傳統(tǒng)的線程相比,虛擬線程具有更低的創(chuàng)建和銷毀成本,可以更好地利用系統(tǒng)資源。

圖片圖片

虛擬線程的主要優(yōu)勢:

  1. 高并發(fā)性:由于虛擬線程的創(chuàng)建和銷毀成本低,因此可以在短時間內(nèi)創(chuàng)建大量的虛擬線程,實現(xiàn)高并發(fā)處理。
  2. 資源利用率高:虛擬線程可以共享同一個進程的資源,如內(nèi)存空間、文件描述符等,避免了資源的浪費,提高了系統(tǒng)的資源利用率。
  3. 易于管理和觀察:虛擬線程是輕量級的,其創(chuàng)建、切換和管理都更加簡單和快速。此外,由于虛擬線程共享同一個進程的資源,因此可以使用現(xiàn)有的工具和框架來觀察和管理虛擬線程。

「虛擬線程與平臺線程的區(qū)別」:

  1. 虛擬線程是守護線程,不能通過setDaemon(false)方法將其更改為非守護線程。當(dāng)所有啟動的非守護進程線程都終止時,JVM將終止,這意味著JVM不會等待虛擬線程完成后才退出。
  2. 虛擬線程的優(yōu)先級始終為normal,并且不能通過setPriority()方法更改。在虛擬線程上調(diào)用此方法沒有效果。
  3. 虛擬線程不支持stop()、suspend()或resume()等方法。在虛擬線程上調(diào)用這些方法將拋出UnsupportedOperationException異常。
  4. 虛擬線程并不與特定的操作系統(tǒng)線程綁定,其與操作系統(tǒng)線程的映射關(guān)系比例也不是1:1,而是m:n。虛擬線程通常是由Java運行時來調(diào)度的,而不是操作系統(tǒng)。當(dāng)在虛擬線程中運行的代碼調(diào)用阻塞的I/O操作時,Java運行時會將虛擬線程掛起,直到其可以恢復(fù)為止。

「如何使用虛擬線程」:通過Thread.startVirtualThread()可以運行一個虛擬線程:

Thread.startVirtualThread(() -> {
    System.out.println("虛擬線程執(zhí)行中...");
});

通過Thread.Builder也可以創(chuàng)建虛擬線程,Thread類提供了ofPlatform()來創(chuàng)建一個平臺線程、ofVirtual()來創(chuàng)建虛擬現(xiàn)場。

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線程池的設(shè)計是為了避免創(chuàng)建新的操作系統(tǒng)線程的開銷,但是創(chuàng)建虛擬線程的開銷并不大,所以其實沒必要放到線程池中。

「性能差異」從Runnable創(chuàng)建10000個線程,并使用虛擬線程和平臺線程執(zhí)行它們,以比較兩者的性能。

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());
};

傳統(tǒng)線程實現(xiàn):

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);

虛擬線程實現(xiàn):

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);

最終結(jié)果:

總耗時 : 102323
總耗時 : 1674

100秒和1.6秒的差距,虛擬線程的性能提升還是比較大的。

Java虛擬線程相對于傳統(tǒng)線程具有更好的性能表現(xiàn),特別是在高并發(fā)場景下。但是需要注意的是,虛擬線程并不是萬能的,過度使用虛擬線程也可能會導(dǎo)致其他問題,如線程數(shù)量過多、線程間通信和同步問題等。


責(zé)任編輯:武曉燕 來源: 沐雨花飛蝶
相關(guān)推薦

2023-02-07 20:17:21

JDK19虛擬線程

2023-11-01 07:24:16

JDK19線程

2022-10-17 09:39:13

JDK虛擬線程

2010-05-28 10:24:30

MySQL Event

2022-07-28 07:57:27

JDK 19Java

2023-12-20 14:35:37

Java虛擬線程

2009-07-09 10:28:19

線程池JDK5

2012-08-30 09:34:08

VMware

2022-12-09 09:49:57

JDK19JAVA9版本

2023-10-23 19:51:11

Java線程

2011-11-08 10:30:05

Eclipse

2011-09-08 11:49:55

RadwarevDirect插件

2012-09-07 09:31:55

企業(yè)通信企業(yè)協(xié)作Avaya

2010-04-15 00:46:20

CompuwareChangepoint

2022-11-29 11:00:04

Lambda表達(dá)式Java

2019-03-04 09:39:41

Java開發(fā)代碼

2019-08-26 10:36:22

6G5G網(wǎng)絡(luò)

2013-01-11 09:30:02

諾基亞PureViewLumia

2021-06-25 10:24:30

Google開源漏洞數(shù)據(jù)庫

2016-03-01 09:37:03

IBM認(rèn)知論壇outthinkIBM
點贊
收藏

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