在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

探索虛擬線程:原理與實現

京東云 ? 來源:jf_75140285 ? 作者:jf_75140285 ? 2024-06-24 11:35 ? 次閱讀

虛擬線程的引入與優勢

在Loom項目之前,Java虛擬機(JVM)中的線程是通過java.lang.Thread類型來實現的,這些線程被稱為平臺線程。

然而,平臺線程的創建和維護在資源使用上存在顯著的開銷。首先,創建成本不菲,因為每當操作系統需要創建一個新的平臺線程時,它必須分配大量的內存(通常以兆字節計)來存儲線程的上下文信息、本機棧和Java調用棧。這一過程受到固定大小堆棧的限制,導致創建和調度平臺線程時的開銷在空間和時間上都相當巨大。此外,當調度器需要從當前執行的線程中搶占時,必須處理大量內存的移動,這進一步增加了操作的復雜性和成本。這種開銷不僅限制了可以同時創建的線程數量,而且也容易導致內存資源的耗盡。以下是一個示例,展示了在Java中如何通過不斷實例化新的平臺線程,迅速達到內存耗盡的情況:

private static void stackOverflowErrorDemo() {
    try {
        int threadCount = 0;
        // 嘗試創建高達百萬級的線程數量
        while (threadCount++ < 100000000) {
            // 創建并啟動一個新線程
            Thread thread = new Thread(() -?> {
                try {
                    // 線程休眠1秒,模擬長時間運行的任務
                    Thread.sleep(Duration.ofSeconds(1));
                } catch (InterruptedException e) {
                    // 如果線程被中斷,將其轉換為運行時異常
                    throw new RuntimeException(e);
                }
            });
            // 啟動線程
            thread.start();
        }
    } catch (RuntimeException e) {
        // 捕獲并處理由線程啟動過程中可能拋出的運行時異常
        e.printStackTrace();
    }
}

在實際操作中,達到OutOfMemoryError的時間會根據操作系統和硬件的不同而有所差異。然而,通常情況下,這個過程可以在極短的時間內完成。

為了解決這些問題,虛擬線程應運而生。

虛擬線程的優勢

資源效率:虛擬線程在內存使用上更為高效,初始內存占用通常只有幾百字節,遠小于平臺線程所需的幾兆字節。

簡化線程管理:虛擬線程的創建和管理過程更為簡便,通過工廠方法可以輕松創建,無需手動管理線程資源。

避免線程爆炸:由于資源消耗低,虛擬線程可以處理大量并發任務,而不必擔心資源耗盡。

協作調度:虛擬線程采用協作調度模型,減少了鎖競爭和上下文切換的開銷,提升了多線程程序的性能。

避免阻塞:虛擬線程在遇到阻塞操作時可以釋放執行權,允許其他線程執行,提高了程序的響應性。

虛擬線程如何創建

創建虛擬線程是Java中的一項新特性,它旨在解決傳統平臺線程所面臨的資源限制問題。虛擬線程作為java.lang.Thread的一個替代實現,其獨特之處在于將線程的調用堆棧存儲在Java堆內存中,而不是傳統的本地線程堆棧中。這種方式顯著減少了每個線程所需的初始內存占用,通常僅為幾百字節,而不是幾兆字節。更進一步,虛擬線程的堆棧大小是動態可變的,這使得我們無需為各種用例預分配大量內存。以下是創建虛擬線程的兩種方法:

使用工廠方法創建虛擬線程

通過java.lang.Thread的ofVirtual靜態工廠方法,我們可以輕松創建虛擬線程。首先,定義一個輔助函數來創建并啟動一個帶有指定名稱的虛擬線程:

private static Thread createVirtualThread(String name, Runnable runnable) {
    return Thread.ofVirtual()
            .name(name)
            .start(runnable);
}

使用ThreadPerTaskExecutor創建虛擬線程

另一種方法是使用專為虛擬線程設計的java.util.concurrent.ExecutorService實現,即ThreadPerTaskExecutor。這個執行器為提交的每個任務創建一個新的虛擬線程:

@SneakyThrows
static void createVirtualThreadUsingExecutorsWithName() {
  final ThreadFactory factory = Thread.ofVirtual().name("worker-", 0).factory();
  try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
    var cleanTime =
      executor.submit(
        () -> {
          log.info("我要打掃衛生");
          sleep(Duration.ofMillis(500L));
          log.info("衛生打掃完了");
         });
    var boilingWater =
      executor.submit(
        () -> {
          log.info("我要去燒一些水");
          sleep(Duration.ofSeconds(1L));
          log.info("水燒好了");
        });
    cleanTime.get();
    boilingWater.get();
  }
}

在這個示例中,我們使用了submit方法來啟動虛擬線程,它需要一個Runnable或Callable任務。submit方法返回一個Future對象,該對象可以用來跟蹤和控制虛擬線程的執行。

虛擬線程的啟動和同步

與平臺線程相比,虛擬線程的啟動和同步方式略有不同,因為它們是通過ExecutorService來管理的。每個submit調用都返回一個Future對象,這允許我們跟蹤任務的狀態,甚至在必要時阻塞當前線程直到虛擬線程完成其任務。

虛擬線程的原理

wKgaomZ46XiAVMJUAAM2pHHfAVk296.png

??

如上圖所示展示虛擬線程與平臺線程之間的關系:

JVM維護了一個由專用ForkJoinPool創建和維護的平臺線程池。最初,平臺線程的數量等于CPU核心的數量,最多不能超過256個。

對于每個創建的虛擬線程,JVM都會將其執行調度到一個平臺線程上,臨時將虛擬線程的堆棧塊從堆復制到平臺線程的堆棧中。我們說平臺線程變成了虛擬線程的載體線程。

我們可以通過運行使用ThreadPerTaskExecutor創建虛擬線程的用例,觀察其中的一條日志來說明執行過程:

10:30:35.390 [worker-1] INFO in.rcard.virtual.threads.App - VirtualThread[#23,worker-1]/runnable@ForkJoinPool-1-worker-2 | 我要去燒一些水

從日志中進行觀察

1. 線程標識與命名:每個虛擬線程都有一個唯一的標識符和名稱,例如 `VirtualThread[#23,worker-1]`。這里的 `#23` 表示線程的編號,而 `worker-1` 是線程的名稱,它們共同幫助開發者識別和調試線程。

2. 載體線程的分配:虛擬線程執行時,會綁定到一個特定的載體線程(即平臺線程)。例如,`ForkJoinPool-1-worker-2` 表示該虛擬線程正在由默認的ForkJoinPool中的第二個工作線程執行。

3. 阻塞與釋放:當虛擬線程遇到阻塞操作時,其載體線程會被釋放,以便能夠執行其他就緒的虛擬線程。同時,虛擬線程的堆棧塊會從載體線程的堆棧復制回Java堆中,以等待阻塞操作的完成。

4. 再次調度:一旦虛擬線程完成其阻塞操作,調度器會將其重新排入執行隊列。虛擬線程可能會繼續在先前的載體線程上執行,或者根據調度器的決策,在不同的載體線程上繼續執行。

剛才我們提到,默認情況下,JVM會創建與cpu核心數量相等的載體線程(平臺線程),以確保每個物理核心都能被有效利用。那么假如計算機上配備了2個物理核心和通過超線程技術支持的4個邏輯核心,基于此硬件配置,我們可以設計一個程序,該程序旨在生成與邏輯核心數相匹配的虛擬線程數量,即4個虛擬線程。然而,為了探索線程調度的靈活性,我們可以增加一個額外的虛擬線程,使得總數達到5個,即期望5個虛擬線程在4個載體線程上執行,那么至少會有一個載體線程會被重復使用。執行以下程序

static void viewCarrierThreadPoolSize() {
  final ThreadFactory factory = Thread.ofVirtual().name("worker-", 0).factory();
  try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
    IntStream.range(0, numberOfCores() + 1)
        .forEach(i -> executor.submit(() -> {
          log.info("virtual thread number " + i);
          sleep(Duration.ofSeconds(1L));
        }));
  }
}
[worker-0] INFO in.rcard.virtual.threads.App - VirtualThread[#21,worker-0]/runnable@ForkJoinPool-1-worker-1 | virtual thread number 0
[worker-1] INFO in.rcard.virtual.threads.App - VirtualThread[#23,worker-1]/runnable@ForkJoinPool-1-worker-2 | virtual thread number 1
[worker-2] INFO in.rcard.virtual.threads.App - VirtualThread[#24,worker-2]/runnable@ForkJoinPool-1-worker-3 | virtual thread number 2
[worker-4] INFO in.rcard.virtual.threads.App - VirtualThread[#26,worker-4]/runnable@ForkJoinPool-1-worker-4 | virtual thread number 4
[worker-3] INFO in.rcard.virtual.threads.App - VirtualThread[#25,worker-3]/runnable@ForkJoinPool-1-worker-4 | virtual thread number 3

觀察日志,有四個載體線程,分別是ForkJoinPool-1-worker-1、ForkJoinPool-1-worker-2、ForkJoinPool-1-worker-3和ForkJoinPool-1-worker-4,ForkJoinPool-1-worker-4被重復使用了兩次,以上假設正確。

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 存儲
    +關注

    關注

    13

    文章

    4507

    瀏覽量

    87112
  • 操作系統
    +關注

    關注

    37

    文章

    7103

    瀏覽量

    125034
  • 虛擬
    +關注

    關注

    0

    文章

    198

    瀏覽量

    23919
  • 虛擬機
    +關注

    關注

    1

    文章

    963

    瀏覽量

    29109
  • 線程
    +關注

    關注

    0

    文章

    507

    瀏覽量

    20098
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    鴻蒙5開發寶藏案例分享---跨線程性能優化指南

    , bookList); // 卡在主線程序列化! 改造后 (<8ms): // 關鍵:實現Sendable接口! class Book implements Sendable
    發表于 06-12 17:13

    進程、線程、協程傻傻分不清?一文帶你徹底扒光它們的\"底褲\"!

    /file0 線程1 下載開始 http://example.com/file1 ...(并行執行) 所有下載完成! 第三章:協程——程序界的「時間管理大師」 定義:用戶態的「虛擬線程」,靠主動讓
    發表于 03-26 09:27

    請問如何在Python中實現線程與多進程的協作?

    大家好!我最近在開發一個Python項目時,需要同時處理多個任務,且每個任務需要不同的計算資源。我想通過多線程和多進程的組合來實現并發,但遇到了一些問題。 具體來說,我有兩個任務,一個是I/O密集型
    發表于 03-11 06:57

    摩爾線程完成DeepSeek開源庫FlashMLA和DeepGEMM適配

    MUTLASS,快速支持了FlashMLA。不僅如此,摩爾線程還基于MUTLASS在全新GPU架構上優化實現了FP8矩陣乘法,支持DeepGEMM的相應功能,充分展示了摩爾線程MUSA架構和全功能GPU在生態兼容與快速適配上的強
    的頭像 發表于 02-27 14:40 ?507次閱讀

    摩爾線程宣布成功部署DeepSeek蒸餾模型推理服務

    近日,摩爾線程智能科技(北京)有限責任公司在其官方渠道發布了一則重要消息,宣布公司已經成功實現了對DeepSeek蒸餾模型推理服務的部署。這一技術突破,標志著摩爾線程在人工智能領域邁出了堅實的一步
    的頭像 發表于 02-06 13:49 ?738次閱讀

    探索字節隊列的魔法:多類型支持、函數重載與線程安全

    探索字節隊列的魔法:多類型支持、函數重載與線程安全代碼難度指數:文章學習重點:參數宏的使用技巧一、引言在嵌入式系統和實時應用中,數據的傳輸和處理是至關重要的。字節隊列(ByteQueue)是一種重要
    的頭像 發表于 11-15 01:08 ?1190次閱讀
    <b class='flag-5'>探索</b>字節隊列的魔法:多類型支持、函數重載與<b class='flag-5'>線程</b>安全

    socket 多線程編程實現方法

    在現代網絡編程中,多線程技術被廣泛應用于提高服務器的并發處理能力。Socket編程是網絡通信的基礎,而將多線程技術應用于Socket編程,可以顯著提升服務器的性能。 多線程編程的基本概念 多
    的頭像 發表于 11-12 14:16 ?915次閱讀

    摩爾線程完成股改,籌備上市

    近日,摩爾線程智能科技(北京)股份有限公司(簡稱“摩爾線程”)宣布已完成股改,并正積極籌備上市。據國家企業信用信息公示系統最新查詢結果顯示,摩爾線程的市場主體類型在10月28日已從其他有限責任公司
    的頭像 發表于 11-12 14:15 ?1068次閱讀

    Python中多線程和多進程的區別

    Python作為一種高級編程語言,提供了多種并發編程的方式,其中多線程與多進程是最常見的兩種方式之一。在本文中,我們將探討Python中多線程與多進程的概念、區別以及如何使用線程池與進程池來提高并發執行效率。
    的頭像 發表于 10-23 11:48 ?937次閱讀
    Python中多<b class='flag-5'>線程</b>和多進程的區別

    虛擬桌面基礎架構(VDI)遠程連接如何實現

    今天我們來聊聊虛擬桌面基礎架構(VDI)。VDI的工作原理是將桌面虛擬化,使得用戶可以通過網絡連接訪問虛擬機,確保數據和應用保存在服務器上,提高數據的安全性。使用VDI通常涉及以下步驟1、部署
    的頭像 發表于 10-18 08:09 ?742次閱讀
    <b class='flag-5'>虛擬</b>桌面基礎架構(VDI)遠程連接如何<b class='flag-5'>實現</b>

    鴻蒙跨端實踐-JS虛擬機架構實現

    類似的框架,我們需要自行實現以確保核心基礎能力的完整。 鴻蒙虛擬機的開發經歷了從最初 ArkTs2V8 到 JSVM + Roma新架構方案 。在此過程中,我們實現了完整的鴻蒙版的“J2V8”和 基于系統JSVM的JS
    的頭像 發表于 09-30 14:42 ?2899次閱讀
    鴻蒙跨端實踐-JS<b class='flag-5'>虛擬</b>機架構<b class='flag-5'>實現</b>

    CPU線程和程序線程的區別

    CPU的線程與程序的線程在概念、作用、實現方式以及性能影響等方面存在顯著差異。以下是對兩者區別的詳細闡述,旨在深入探討這一技術話題。
    的頭像 發表于 09-02 11:18 ?1968次閱讀

    摩爾線程與羽人科技完成大語言模型訓練測試

    近日,摩爾線程與羽人科技攜手宣布,雙方已成功實現夸娥(KUAE)千卡智算集群與羽人系列模型解決方案的訓練兼容適配。在本次測試中,羽人科技通過摩爾線程夸娥千卡智算集群,高效完成了70億參數羽人7B
    的頭像 發表于 08-27 16:19 ?777次閱讀

    Java CompletableFuture 異步超時實現探索

    簡介 JDK 8 中 CompletableFuture 沒有超時中斷任務的能力。現有做法強依賴任務自身的超時實現。本文提出一種異步超時實現方案,解決上述問題。 前言 JDK 8 是一次重大的版本
    的頭像 發表于 07-25 14:06 ?621次閱讀

    鴻蒙開發:線程模型

    FA模型下的線程主要有如下三類
    的頭像 發表于 06-24 17:27 ?663次閱讀
    鴻蒙開發:<b class='flag-5'>線程</b>模型
    主站蜘蛛池模板: 国产女同在线观看 | 成人a大片高清在线观看 | 成人免费看黄网站yyy456 | 婷婷色综合久久 | 午夜色站| 妇少香港三日本三级视频 | 亚洲高清免费视频 | 欧美三级网址 | 天天操天天操天天操天天操 | chinese国产videoxx实拍 | 天天做天天操 | 日本不卡在线观看 | 日本在线视频www色 日本在线视频精品 | 神马午夜第九 | 天天爱天天干天天 | 香蕉免费在线视频 | 欧美性白人极品1819hd | 一级特黄牲大片免费视频 | 久久福利青草精品资源站免费 | 欧美一级精品高清在线观看 | 五月天男人的天堂 | 日韩a视频| 欧美疯狂爱爱xxxxbbbb | 欧洲另类一二三四区 | 美女拍拍拍爽爽爽爽爽爽 | 办公室桌震娇喘视频大全在线 | 欧美福利视频网站 | www欧美在线观看 | 成 黄 色 激 情视频网站 | 日本三级强在线观看 | 四虎影像| 天天干夜干 | 亚洲成色在线综合网站 | 久热精品视频 | 成人国产三级精品 | 国产成人精品一区二区仙踪林 | 亚洲日本在线观看 | 久久九九国产精品怡红院 | bt天堂网在线www资源 | 偷偷鲁影院手机在线观看 | 国产jlzzjlzz视频免费 |