一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

探索虛擬線程:原理與實(shí)現(xiàn)

京東云 ? 來(lái)源:jf_75140285 ? 作者:jf_75140285 ? 2024-06-24 11:35 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

虛擬線程的引入與優(yōu)勢(shì)

在Loom項(xiàng)目之前,Java虛擬機(jī)(JVM)中的線程是通過java.lang.Thread類型來(lái)實(shí)現(xiàn)的,這些線程被稱為平臺(tái)線程。

然而,平臺(tái)線程的創(chuàng)建和維護(hù)在資源使用上存在顯著的開銷。首先,創(chuàng)建成本不菲,因?yàn)槊慨?dāng)操作系統(tǒng)需要?jiǎng)?chuàng)建一個(gè)新的平臺(tái)線程時(shí),它必須分配大量的內(nèi)存(通常以兆字節(jié)計(jì))來(lái)存儲(chǔ)線程的上下文信息、本機(jī)棧和Java調(diào)用棧。這一過程受到固定大小堆棧的限制,導(dǎo)致創(chuàng)建和調(diào)度平臺(tái)線程時(shí)的開銷在空間和時(shí)間上都相當(dāng)巨大。此外,當(dāng)調(diào)度器需要從當(dāng)前執(zhí)行的線程中搶占時(shí),必須處理大量?jī)?nèi)存的移動(dòng),這進(jìn)一步增加了操作的復(fù)雜性和成本。這種開銷不僅限制了可以同時(shí)創(chuàng)建的線程數(shù)量,而且也容易導(dǎo)致內(nèi)存資源的耗盡。以下是一個(gè)示例,展示了在Java中如何通過不斷實(shí)例化新的平臺(tái)線程,迅速達(dá)到內(nèi)存耗盡的情況:

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

在實(shí)際操作中,達(dá)到OutOfMemoryError的時(shí)間會(huì)根據(jù)操作系統(tǒng)和硬件的不同而有所差異。然而,通常情況下,這個(gè)過程可以在極短的時(shí)間內(nèi)完成。

為了解決這些問題,虛擬線程應(yīng)運(yùn)而生。

虛擬線程的優(yōu)勢(shì)

資源效率:虛擬線程在內(nèi)存使用上更為高效,初始內(nèi)存占用通常只有幾百字節(jié),遠(yuǎn)小于平臺(tái)線程所需的幾兆字節(jié)。

簡(jiǎn)化線程管理:虛擬線程的創(chuàng)建和管理過程更為簡(jiǎn)便,通過工廠方法可以輕松創(chuàng)建,無(wú)需手動(dòng)管理線程資源。

避免線程爆炸:由于資源消耗低,虛擬線程可以處理大量并發(fā)任務(wù),而不必?fù)?dān)心資源耗盡。

協(xié)作調(diào)度:虛擬線程采用協(xié)作調(diào)度模型,減少了鎖競(jìng)爭(zhēng)和上下文切換的開銷,提升了多線程程序的性能。

避免阻塞:虛擬線程在遇到阻塞操作時(shí)可以釋放執(zhí)行權(quán),允許其他線程執(zhí)行,提高了程序的響應(yīng)性。

虛擬線程如何創(chuàng)建

創(chuàng)建虛擬線程是Java中的一項(xiàng)新特性,它旨在解決傳統(tǒng)平臺(tái)線程所面臨的資源限制問題。虛擬線程作為java.lang.Thread的一個(gè)替代實(shí)現(xiàn),其獨(dú)特之處在于將線程的調(diào)用堆棧存儲(chǔ)在Java堆內(nèi)存中,而不是傳統(tǒng)的本地線程堆棧中。這種方式顯著減少了每個(gè)線程所需的初始內(nèi)存占用,通常僅為幾百字節(jié),而不是幾兆字節(jié)。更進(jìn)一步,虛擬線程的堆棧大小是動(dòng)態(tài)可變的,這使得我們無(wú)需為各種用例預(yù)分配大量?jī)?nèi)存。以下是創(chuàng)建虛擬線程的兩種方法:

使用工廠方法創(chuàng)建虛擬線程

通過java.lang.Thread的ofVirtual靜態(tài)工廠方法,我們可以輕松創(chuàng)建虛擬線程。首先,定義一個(gè)輔助函數(shù)來(lái)創(chuàng)建并啟動(dòng)一個(gè)帶有指定名稱的虛擬線程:

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

使用ThreadPerTaskExecutor創(chuàng)建虛擬線程

另一種方法是使用專為虛擬線程設(shè)計(jì)的java.util.concurrent.ExecutorService實(shí)現(xiàn),即ThreadPerTaskExecutor。這個(gè)執(zhí)行器為提交的每個(gè)任務(wù)創(chuàng)建一個(gè)新的虛擬線程:

@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("我要打掃衛(wèi)生");
          sleep(Duration.ofMillis(500L));
          log.info("衛(wèi)生打掃完了");
         });
    var boilingWater =
      executor.submit(
        () -> {
          log.info("我要去燒一些水");
          sleep(Duration.ofSeconds(1L));
          log.info("水燒好了");
        });
    cleanTime.get();
    boilingWater.get();
  }
}

在這個(gè)示例中,我們使用了submit方法來(lái)啟動(dòng)虛擬線程,它需要一個(gè)Runnable或Callable任務(wù)。submit方法返回一個(gè)Future對(duì)象,該對(duì)象可以用來(lái)跟蹤和控制虛擬線程的執(zhí)行。

虛擬線程的啟動(dòng)和同步

與平臺(tái)線程相比,虛擬線程的啟動(dòng)和同步方式略有不同,因?yàn)樗鼈兪峭ㄟ^ExecutorService來(lái)管理的。每個(gè)submit調(diào)用都返回一個(gè)Future對(duì)象,這允許我們跟蹤任務(wù)的狀態(tài),甚至在必要時(shí)阻塞當(dāng)前線程直到虛擬線程完成其任務(wù)。

虛擬線程的原理

wKgaomZ46XiAVMJUAAM2pHHfAVk296.png

??

如上圖所示展示虛擬線程與平臺(tái)線程之間的關(guān)系:

JVM維護(hù)了一個(gè)由專用ForkJoinPool創(chuàng)建和維護(hù)的平臺(tái)線程池。最初,平臺(tái)線程的數(shù)量等于CPU核心的數(shù)量,最多不能超過256個(gè)。

對(duì)于每個(gè)創(chuàng)建的虛擬線程,JVM都會(huì)將其執(zhí)行調(diào)度到一個(gè)平臺(tái)線程上,臨時(shí)將虛擬線程的堆棧塊從堆復(fù)制到平臺(tái)線程的堆棧中。我們說(shuō)平臺(tái)線程變成了虛擬線程的載體線程。

我們可以通過運(yùn)行使用ThreadPerTaskExecutor創(chuàng)建虛擬線程的用例,觀察其中的一條日志來(lái)說(shuō)明執(zhí)行過程:

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

從日志中進(jìn)行觀察

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

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

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

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

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

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

觀察日志,有四個(gè)載體線程,分別是ForkJoinPool-1-worker-1、ForkJoinPool-1-worker-2、ForkJoinPool-1-worker-3和ForkJoinPool-1-worker-4,F(xiàn)orkJoinPool-1-worker-4被重復(fù)使用了兩次,以上假設(shè)正確。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 存儲(chǔ)
    +關(guān)注

    關(guān)注

    13

    文章

    4517

    瀏覽量

    87244
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    7122

    瀏覽量

    125256
  • 虛擬
    +關(guān)注

    關(guān)注

    0

    文章

    198

    瀏覽量

    23939
  • 虛擬機(jī)
    +關(guān)注

    關(guān)注

    1

    文章

    966

    瀏覽量

    29217
  • 線程
    +關(guān)注

    關(guān)注

    0

    文章

    508

    瀏覽量

    20130
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    鴻蒙5開發(fā)寶藏案例分享---跨線程性能優(yōu)化指南

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

    進(jìn)程、線程、協(xié)程傻傻分不清?一文帶你徹底扒光它們的\"底褲\"!

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

    請(qǐng)問如何在Python中實(shí)現(xiàn)線程與多進(jìn)程的協(xié)作?

    大家好!我最近在開發(fā)一個(gè)Python項(xiàng)目時(shí),需要同時(shí)處理多個(gè)任務(wù),且每個(gè)任務(wù)需要不同的計(jì)算資源。我想通過多線程和多進(jìn)程的組合來(lái)實(shí)現(xiàn)并發(fā),但遇到了一些問題。 具體來(lái)說(shuō),我有兩個(gè)任務(wù),一個(gè)是I/O密集型
    發(fā)表于 03-11 06:57

    摩爾線程完成DeepSeek開源庫(kù)FlashMLA和DeepGEMM適配

    MUTLASS,快速支持了FlashMLA。不僅如此,摩爾線程還基于MUTLASS在全新GPU架構(gòu)上優(yōu)化實(shí)現(xiàn)了FP8矩陣乘法,支持DeepGEMM的相應(yīng)功能,充分展示了摩爾線程MUSA架構(gòu)和全功能GPU在生態(tài)兼容與快速適配上的強(qiáng)
    的頭像 發(fā)表于 02-27 14:40 ?532次閱讀

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

    近日,摩爾線程智能科技(北京)有限責(zé)任公司在其官方渠道發(fā)布了一則重要消息,宣布公司已經(jīng)成功實(shí)現(xiàn)了對(duì)DeepSeek蒸餾模型推理服務(wù)的部署。這一技術(shù)突破,標(biāo)志著摩爾線程在人工智能領(lǐng)域邁出了堅(jiān)實(shí)的一步
    的頭像 發(fā)表于 02-06 13:49 ?757次閱讀

    探索字節(jié)隊(duì)列的魔法:多類型支持、函數(shù)重載與線程安全

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

    socket 多線程編程實(shí)現(xiàn)方法

    在現(xiàn)代網(wǎng)絡(luò)編程中,多線程技術(shù)被廣泛應(yīng)用于提高服務(wù)器的并發(fā)處理能力。Socket編程是網(wǎng)絡(luò)通信的基礎(chǔ),而將多線程技術(shù)應(yīng)用于Socket編程,可以顯著提升服務(wù)器的性能。 多線程編程的基本概念 多
    的頭像 發(fā)表于 11-12 14:16 ?957次閱讀

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

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

    Python中多線程和多進(jìn)程的區(qū)別

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

    虛擬桌面基礎(chǔ)架構(gòu)(VDI)遠(yuǎn)程連接如何實(shí)現(xiàn)

    今天我們來(lái)聊聊虛擬桌面基礎(chǔ)架構(gòu)(VDI)。VDI的工作原理是將桌面虛擬化,使得用戶可以通過網(wǎng)絡(luò)連接訪問虛擬機(jī),確保數(shù)據(jù)和應(yīng)用保存在服務(wù)器上,提高數(shù)據(jù)的安全性。使用VDI通常涉及以下步驟1、部署
    的頭像 發(fā)表于 10-18 08:09 ?771次閱讀
    <b class='flag-5'>虛擬</b>桌面基礎(chǔ)架構(gòu)(VDI)遠(yuǎn)程連接如何<b class='flag-5'>實(shí)現(xiàn)</b>

    鴻蒙跨端實(shí)踐-JS虛擬機(jī)架構(gòu)實(shí)現(xiàn)

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

    CPU線程和程序線程的區(qū)別

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

    摩爾線程與羽人科技完成大語(yǔ)言模型訓(xùn)練測(cè)試

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

    Java CompletableFuture 異步超時(shí)實(shí)現(xiàn)探索

    簡(jiǎn)介 JDK 8 中 CompletableFuture 沒有超時(shí)中斷任務(wù)的能力。現(xiàn)有做法強(qiáng)依賴任務(wù)自身的超時(shí)實(shí)現(xiàn)。本文提出一種異步超時(shí)實(shí)現(xiàn)方案,解決上述問題。 前言 JDK 8 是一次重大的版本
    的頭像 發(fā)表于 07-25 14:06 ?650次閱讀

    摩爾線程與樂創(chuàng)能源共同研發(fā)能源大模型

    在數(shù)字化轉(zhuǎn)型的浪潮中,新能源行業(yè)正迎來(lái)前所未有的發(fā)展機(jī)遇與挑戰(zhàn)。為加速這一領(lǐng)域的智能化進(jìn)程,摩爾線程與樂創(chuàng)能源近日正式簽署了戰(zhàn)略合作協(xié)議,標(biāo)志著雙方在能源大模型的創(chuàng)新與應(yīng)用上邁出了堅(jiān)實(shí)的一步。此次合作,不僅是對(duì)新能源技術(shù)邊界的勇敢探索,更是對(duì)未來(lái)能源管理體系智能化升級(jí)的重
    的頭像 發(fā)表于 07-11 14:55 ?792次閱讀