成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

多線程回答的滾瓜爛熟,面試官問我虛線程了解嗎?我說不太了解!

開發 前端
虛擬線程是由 Java 虛擬機調度,它的占用空間小,同時使用輕量級的任務隊列來調度虛擬線程,避免了線程間基于內核的上下文切換開銷,因此可以極大量地創建和使用。

Java虛擬線程(Virtual Threads)標志著Java在并發編程領域的一次重大飛躍,特別是從Java 21版本開始。這項新技術的引入旨在克服傳統多線程和線程池存在的挑戰。

多線程和線程池

在Java中,傳統的多線程編程依賴于Thread類或實現Runnable接口。這些線程都是重量級的,因為每個線程都對應一個操作系統級的線程,這意味著線程的創建、調度和銷毀都需要操作系統的深度參與,不僅耗費資源,也消耗時間。

圖片圖片

為了優化資源使用和提高效率,Java提供了線程池(ExecutorService等)。線程池可以重用固定數量的線程,避免了頻繁創建和銷毀線程的開銷。然而,即使是線程池也無法完全解決上下文切換和資源消耗的問題,尤其是在高并發場景下。此外,大量的線程創建還可能導致OutOfMemoryError。

下面是一個線程池OutOfMemoryError的例子:

public static void main(String[] args) {
    stackOverFlowErrorExample();
}

private static void stackOverFlowErrorExample() {
    for (int i = 0; i < 100_000; i++) {
        new Thread(() -> {
            try {
                Thread.sleep(Duration.ofSeconds(1L));
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();
    }
}

圖片圖片

虛擬線程引入

為了進一步提高并發編程的效率和簡化開發過程,Java19引入了虛擬線程概念。這些輕量級的線程在JVM的用戶模式下被管理,而不是直接映射到操作系統的線程上。這種設計使得可以創建數百萬個虛擬線程,而對操作系統資源的消耗微乎其微。

當代碼調用到阻塞操作時例如 IO、同步、Sleep等操作時,JVM 會自動把 Virtual Thread 從平臺線程上卸載,平臺線程就會去處理下一個虛擬線程,通過這種方式,提升了平臺線程的利用率,讓平臺線程不再阻塞在等待上,從底層實現了少量平臺線程就可以處理大量請求,提高了服務吞吐和 CPU 的利用率。

圖片圖片

? 操作系統線程(OS Thread):由操作系統管理,是操作系統調度的基本單位。

? 平臺線程(Platform Thread):傳統方式使用的Java.Lang.Thread,都是一個平臺線程,是 Java 對操作系統線程的包裝,與操作系統是 1:1 映射。

? 虛擬線程(Virtual Thread):一種輕量級,由 JVM 管理的線程。對應的實例 java.lang.VirtualThread 這個類。

? 載體線程(Carrier Thread):指真正負責執行虛擬線程中任務的平臺線程。一個虛擬線程裝載到一個平臺線程之后,那么這個平臺線程就被稱為虛擬線程的載體線程。

使用虛擬線程

虛擬線程的使用接口與普通線程相似,但創建虛擬線程的方式略有不同。以下是幾種創建和使用虛擬線程的方法:

  • 直接創建虛擬線程并運行:
// 傳入Runnable實例并立刻運行:
Thread vt = Thread.startVirtualThread(() -> {
    System.out.println("Start virtual thread...");
    Thread.sleep(10);
    System.out.println("End virtual thread.");
});
  • 創建虛擬線程但不自動運行,而是手動調用start()開始運行:
// 創建VirtualThread:
Thread.ofVirtual().unstarted(() -> {
    System.out.println("Start virtual thread...");
    Thread.sleep(1000);
    System.out.println("End virtual thread.");
});
// 運行:
vt.start();
  • 通過虛擬線程的ThreadFactory創建虛擬線程,然后手動調用start()開始運行:
// 創建ThreadFactory:
ThreadFactory tf = Thread.ofVirtual().factory();
// 創建VirtualThread:
Thread vt = tf.newThread(() -> {
    System.out.println("Start virtual thread...");
    Thread.sleep(1000);
    System.out.println("End virtual thread.");
});
// 運行:
vt.start();

直接調用start()實際上是由ForkJoinPool的線程來調度的。我們也可以自己創建調度線程,然后運行虛擬線程:

ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
// 創建大量虛擬線程并調度:
ThreadFactory tf = Thread.ofVirtual().factory();
for (int i=0; i<100_000; i++) {
    Thread vt = tf.newThread(() -> { ... });
    executor.submit(vt);
    executor.submit(() -> {
        System.out.println("Start virtual thread...");
        Thread.sleep(Duration.ofSeconds(1L));
        System.out.println("End virtual thread.");
        return true;
    });
}

由于虛擬線程屬于非常輕量級的資源,因此,用時創建,用完就扔,不要池化虛擬線程。

虛線程的性能

下面我們測試一下虛線程的性能

public static void main(String[] args) {
    testWithVirtualThread();

    testWithThread(20);
    testWithThread(50);
    testWithThread(100);
    testWithThread(200);
    testWithThread(400);
}

private static long testWithVirtualThread() {
    long start = System.currentTimeMillis();
    ExecutorService es = Executors.newVirtualThreadPerTaskExecutor();
    for (int i = 0; i < TASK_NUM; i++) {
        es.submit(() -> {
            Thread.sleep(100);
            return 0;
        });
    }
    es.close();
    long end = System.currentTimeMillis();
    System.out.println("virtual thread:" + (end - start));
    return end;
}

private static void testWithThread(int threadNum) {
    long start = System.currentTimeMillis();
    ExecutorService es = Executors.newFixedThreadPool(threadNum);
    for (int i = 0; i < TASK_NUM; i++) {
        es.submit(() -> {
            Thread.sleep(100);
            return 0;
        });
    }
    es.close();
    System.out.println(threadNum + " thread:" + (System.currentTimeMillis() - start));
    es.shutdown();
}

下面是測試結果:

圖片圖片

虛線程真是快到飛起!!!

虛擬線程的原理

Java的虛擬線程會把任務(java.lang.Runnable實例)包裝到一個 Continuation實例中。當任務需要阻塞掛起的時候,會調用Continuation 的 yield 操作進行阻塞,虛擬線程會從平臺線程卸載。 當任務解除阻塞繼續執行的時候,調用 Continuation.run會從阻塞點繼續執行。下面讓我們結合Thread.ofVirtual().start()來看一下虛線程的實現。

當調用start()方法時,會創建一個虛擬線程 var thread = newVirtualThread(scheduler, nextThreadName(), characteristics(), task);

static Thread newVirtualThread(Executor scheduler,
                                   String name,
                                   int characteristics,
                                   Runnable task) {
        if (ContinuationSupport.isSupported()) {
            return new VirtualThread(scheduler, name, characteristics, task);
        } else {
            if (scheduler != null)
                throw new UnsupportedOperationException();
            return new BoundVirtualThread(name, characteristics, task);
        }
    }

核心主要在java.lang.VirtualThread類中。下面是JVM 調用VirtualThread的構造函數:

圖片圖片

VirtualThread 會初始化一個ForkJoinPool的Executor.

private static final ForkJoinPool DEFAULT_SCHEDULER = createDefaultScheduler(); 該方法初始化Executor線程池大小。該Executor 也就是執行器,提供了一個默認的 FIFO 的 ForkJoinPool 用于執行虛擬線程任務。

之后創建一個VThreadContinuation對象。該對象存儲作為Runnable對象運行的信息,它確保了每個并發操作都有清晰定義的生命周期和上下文。

VThreadContinuation是一種允許程序執行被暫停并在將來某個時刻恢復的機制。虛擬線程利用VThreadContinuation來實現輕量級的上下文切換.

最后,該方法調用runContinuation方法。該方法在虛擬線程啟動時被調用。

JVM 把虛擬線程分配給平臺線程的操作稱為 mount(掛載),取消分配平臺線程的操作稱為 unmount(卸載)。

Continuation 組件十分重要,它既是用戶真實任務的包裝器,同時提供了虛擬線程任務暫停/繼續的能力,以及虛擬線程與平臺線程數據轉移功能,當任務需要阻塞掛起的時候,調用 Continuation 的 yield 操作進行阻塞。當任務需要解除阻塞繼續執行的時候,則調用 Continuation 的 run 恢復執行。

總結

虛擬線程是由 Java 虛擬機調度,它的占用空間小,同時使用輕量級的任務隊列來調度虛擬線程,避免了線程間基于內核的上下文切換開銷,因此可以極大量地創建和使用。主要有以下好處:

  • 虛擬線程是輕量級的,它們不直接映射到操作系統的線程,而是由JVM在用戶態進行管理。這種輕量級特性允許在單個JVM實例中同時運行數百萬個虛擬線程。
  • 虛擬線程大大簡化了并發編程的復雜性。開發者可以像編寫順序代碼一樣編寫并發代碼,而無需擔心傳統線程編程中的許多復雜問題,如線程數、同步和資源競爭等。
責任編輯:武曉燕 來源: 半畝方塘立身
相關推薦

2022-06-02 09:29:55

線程組線程樹狀結構

2022-06-24 06:43:57

線程池線程復用

2024-09-03 07:58:46

2020-02-24 16:45:38

Java基礎代碼

2022-07-26 08:40:42

Java并發工具類

2022-08-02 06:31:32

Java并發工具類

2021-12-02 08:19:06

MVCC面試數據庫

2020-12-01 11:50:49

數據庫Redis面試

2022-07-11 10:47:46

容器JAVA

2022-06-30 08:14:05

Java阻塞隊列

2022-04-19 07:31:28

事務隔離機制數據庫

2021-05-08 07:53:33

面試線程池系統

2010-03-10 08:54:49

Python多線程

2022-06-06 15:33:20

線程Java釋放鎖

2019-10-31 08:36:59

線程內存操作系統

2022-06-30 14:31:57

Java阻塞隊列

2022-06-10 13:56:42

Java

2020-09-26 22:04:32

數據安全傳輸HTTPSHTTP 協議

2021-01-15 07:23:09

Java線程操作系統

2019-08-28 14:25:00

線程安全容器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品毛片一区二区在线看 | 永久网站 | 国产精品久久久久一区二区三区 | 国产高清视频在线观看 | 久久精品国产一区二区三区 | 精品国产一二三区 | 日韩一区二区在线观看视频 | 天天天操操操 | 一级做a爰片性色毛片16 | 欧美九九九 | 日韩精品视频在线 | 我要看一级片 | 日韩高清一区 | 欧美色999 | 成人二区 | 欧美人妇做爰xxxⅹ性高电影 | 国产欧美日韩综合精品一区二区 | 亚洲精品一区二区三区四区高清 | 婷婷色国产偷v国产偷v小说 | 国产美女特级嫩嫩嫩bbb片 | 一区二区亚洲 | 亚洲毛片在线观看 | 免费性视频 | 国产一区| 美女视频.| 欧美888| 日韩午夜一区二区三区 | 五月激情婷婷在线 | 久久精品色欧美aⅴ一区二区 | 色综合一区二区 | 成人区一区二区三区 | 亚洲视频免费在线 | 国产激情视频在线免费观看 | 国产精品99久久久久久www | a视频在线 | 欧美成人a∨高清免费观看 老司机午夜性大片 | 国产精品久久国产愉拍 | 中国美女撒尿txxxxx视频 | 日韩精品免费一区二区在线观看 | 中文字幕一区在线 | 9久久精品 |