欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java?Thread中join方法使用舉例詳解

 更新時(shí)間:2025年07月26日 09:26:37   作者:干凈的壞蛋  
Java Thread中join()方法主要是讓調(diào)用改方法的thread完成run方法里面的東西后,在執(zhí)行join()方法后面的代碼,這篇文章主要介紹了Java?Thread中join方法使用的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

join() 方法是 Java 并發(fā)編程中一個(gè)非常重要且基礎(chǔ)的方法,它允許一個(gè)線程等待另一個(gè)線程執(zhí)行完成。理解它的工作原理和使用場景對于編寫健壯的多線程應(yīng)用程序至關(guān)重要。

1.join()方法的定義和作用

join()java.lang.Thread 類的一個(gè)實(shí)例方法。它的核心作用是阻塞當(dāng)前正在執(zhí)行的線程(我們稱之為“主線程”,盡管它可以是任何線程),直到調(diào)用 join() 方法的那個(gè)線程(我們稱之為“目標(biāo)線程”)執(zhí)行完畢。

簡單來說,如果線程 A 的代碼中調(diào)用了線程 B 的 join() 方法(即 B.join()),那么線程 A 就會(huì)進(jìn)入等待狀態(tài),直到線程 B 執(zhí)行結(jié)束,線程 A 才會(huì)從 B.join() 這行代碼繼續(xù)往下執(zhí)行。

這就像在一個(gè)接力賽中,下一棒的選手(線程 A)必須等待上一棒的選手(線程 B)跑完自己的賽程并交接后,才能開始跑。

2.join()方法的三個(gè)重載版本

Thread 類提供了三個(gè)版本的 join() 方法:

  1. public final void join()

    • 這是最常用的版本。它會(huì)一直等待,直到目標(biāo)線程執(zhí)行完畢。
    • 它會(huì)拋出 InterruptedException,這意味著等待中的線程可能會(huì)被中斷。
  2. public final synchronized void join(long millis)

    • 這是一個(gè)帶超時(shí)參數(shù)的版本。它會(huì)等待目標(biāo)線程執(zhí)行,但最多只等待指定的毫秒數(shù)。
    • 如果目標(biāo)線程在指定的超時(shí)時(shí)間內(nèi)執(zhí)行完畢,當(dāng)前線程會(huì)立即繼續(xù)執(zhí)行。
    • 如果超過了指定的毫秒數(shù),目標(biāo)線程還未執(zhí)行完,當(dāng)前線程也會(huì)停止等待,繼續(xù)執(zhí)行。
    • 同樣會(huì)拋出 InterruptedException。
  3. public final synchronized void join(long millis, int nanos)

    • 這個(gè)版本提供了更精確的超時(shí)控制,可以指定毫秒和納秒。
    • 功能與 join(long millis) 類似,只是提供了更高精度的時(shí)間控制。

3.join()方法的工作原理 (深入分析)

你可能會(huì)好奇,join() 是如何實(shí)現(xiàn)線程等待的?它的底層原理是什么?

  1. isAlive() 檢查: 當(dāng)你在線程 A 中調(diào)用 threadB.join() 時(shí),join() 方法內(nèi)部會(huì)首先檢查 threadB 是否還活著 (isAlive())。如果 threadB 已經(jīng)執(zhí)行完畢(或者從未啟動(dòng)),isAlive() 會(huì)返回 false,那么 join() 方法會(huì)立即返回,線程 A 不會(huì)進(jìn)行任何等待。

  2. wait() 循環(huán)等待: 如果 isAlive() 返回 true,join() 方法會(huì)進(jìn)入一個(gè)循環(huán)。在這個(gè)循環(huán)里,它會(huì)調(diào)用目標(biāo)線程對象(threadB)的 wait() 方法。

    • 關(guān)鍵點(diǎn): join() 方法是一個(gè) synchronized 方法。當(dāng)線程 A 調(diào)用 threadB.join() 時(shí),它會(huì)獲取 threadB 這個(gè)對象的鎖。然后,join() 方法內(nèi)部調(diào)用 threadB.wait(),這會(huì)導(dǎo)致線程 A 釋放 threadB 的鎖,并進(jìn)入 threadB 對象的等待集(Wait Set)中,狀態(tài)變?yōu)?WAITINGTIMED_WAITING。
  3. JVM 負(fù)責(zé)喚醒: 當(dāng)目標(biāo)線程 threadBrun() 方法執(zhí)行完畢,準(zhǔn)備退出時(shí),Java 虛擬機(jī)(JVM)會(huì)在其內(nèi)部自動(dòng)調(diào)用 threadBnotifyAll() 方法。

    • 這個(gè) notifyAll() 會(huì)喚醒所有正在等待 threadB 對象鎖的線程,當(dāng)然也包括了之前因調(diào)用 join() 而等待的線程 A。
  4. 重新獲取鎖并退出: 線程 A 被喚醒后,會(huì)嘗試重新獲取 threadB 的對象鎖。一旦獲取成功,它會(huì)從 wait() 方法返回,并退出 join() 的循環(huán),從而結(jié)束等待,繼續(xù)執(zhí)行后續(xù)代碼。

總結(jié)一下核心機(jī)制: join() 的實(shí)現(xiàn)巧妙地利用了 Java 的內(nèi)置鎖(synchronized)和 wait()/notifyAll() 協(xié)作機(jī)制。它將線程間的執(zhí)行順序問題,轉(zhuǎn)化為了經(jīng)典的“生產(chǎn)者-消費(fèi)者”模式中的線程同步問題。

4. 為什么要使用join()?使用場景

join() 的主要應(yīng)用場景是協(xié)調(diào)線程間的執(zhí)行順序。當(dāng)你需要確保一個(gè)或多個(gè)前置任務(wù)(在子線程中執(zhí)行)完成后,主線程才能繼續(xù)執(zhí)行后續(xù)任務(wù)時(shí),join() 就非常有用。

常見場景:

  • 數(shù)據(jù)初始化: 主線程啟動(dòng)多個(gè)子線程去分別加載不同的資源或執(zhí)行初始化計(jì)算。主線程需要等待所有初始化工作完成后,才能使用這些資源去執(zhí)行核心業(yè)務(wù)邏輯。
  • 分塊處理: 一個(gè)大任務(wù)被拆分成多個(gè)小任務(wù),每個(gè)小任務(wù)交給一個(gè)子線程處理。主線程需要等待所有子線程處理完畢后,對結(jié)果進(jìn)行匯總和合并。
  • 確保流程順序: 在一個(gè)復(fù)雜的業(yè)務(wù)流程中,步驟 B 必須在步驟 A 執(zhí)行完畢后才能開始。如果 A 和 B 在不同的線程中,那么 B 所在的線程就需要 join() A 所在的線程。

5. 代碼示例

示例 1: 等待單個(gè)線程

public class JoinExample {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("主線程開始運(yùn)行...");

        Thread workerThread = new Thread(() -> {
            System.out.println("子線程開始工作...");
            try {
                // 模擬耗時(shí)操作
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("子線程工作完成。");
        });

        workerThread.start(); // 啟動(dòng)子線程

        System.out.println("主線程調(diào)用 join() 等待子線程...");
        workerThread.join(); // 關(guān)鍵:主線程在此處阻塞,等待 workerThread 執(zhí)行完畢

        System.out.println("主線程在子線程完成后繼續(xù)運(yùn)行。");
    }
}

輸出:

主線程開始運(yùn)行...
主線程調(diào)用 join() 等待子線程...
子線程開始工作...
// (等待約 2 秒)
子線程工作完成。
主線程在子線程完成后繼續(xù)運(yùn)行。

示例 2: 等待多個(gè)線程

public class MultiJoinExample {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("主線程開始...");

        Thread t1 = new Thread(() -> {
            System.out.println("線程1 開始處理...");
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
            System.out.println("線程1 處理完畢。");
        });

        Thread t2 = new Thread(() -> {
            System.out.println("線程2 開始處理...");
            try { Thread.sleep(2000); } catch (InterruptedException e) {}
            System.out.println("線程2 處理完畢。");
        });

        // 啟動(dòng)所有線程
        t1.start();
        t2.start();

        System.out.println("主線程等待所有子線程完成...");

        // 等待 t1 和 t2
        t1.join();
        t2.join();

        System.out.println("所有子線程處理完畢,主線程繼續(xù)執(zhí)行。");
    }
}

輸出:

主線程開始...
主線程等待所有子線程完成...
線程1 開始處理...
線程2 開始處理...
// (等待約 1 秒)
線程1 處理完畢。
// (再等待約 1 秒)
線程2 處理完畢。
所有子線程處理完畢,主線程繼續(xù)執(zhí)行。

6.InterruptedException的處理

join() 方法會(huì)拋出 InterruptedException。這是因?yàn)檎诘却木€程(調(diào)用 join() 的線程)自身可能會(huì)被其他線程中斷 (interrupt())。

當(dāng)一個(gè)線程在 join() 等待期間被中斷時(shí),join() 方法會(huì)立即拋出 InterruptedException。在 catch 塊中,通常需要處理這個(gè)中斷信號。一個(gè)好的實(shí)踐是重新設(shè)置當(dāng)前線程的中斷狀態(tài),以便上層調(diào)用者能夠知道發(fā)生了中斷。

try {
    workerThread.join();
} catch (InterruptedException e) {
    // 捕獲到中斷異常
    System.out.println("主線程在等待期間被中斷了!");
    // 恢復(fù)中斷狀態(tài),這是一種良好的編程實(shí)踐
    Thread.currentThread().interrupt();
}

總結(jié)

特性描述
目的阻塞當(dāng)前線程,等待目標(biāo)線程執(zhí)行完畢。
核心原理基于 synchronizedwait() / notifyAll() 機(jī)制。
版本join(), join(long millis), join(long millis, int nanos)。
使用場景需要保證線程執(zhí)行順序,如等待子任務(wù)完成、數(shù)據(jù)初始化等。
異常拋出 InterruptedException,需要妥善處理線程中斷。
關(guān)鍵點(diǎn)t.join() 是讓當(dāng)前線程等待 t 線程,而不是讓 t 線程等待。

到此這篇關(guān)于Java Thread中join方法使用的文章就介紹到這了,更多相關(guān)Java Thread中join方法使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring?@Conditional注解示例詳細(xì)講解

    Spring?@Conditional注解示例詳細(xì)講解

    @Conditional是Spring4新提供的注解,它的作用是按照一定的條件進(jìn)行判斷,滿足條件給容器注冊bean,這篇文章主要介紹了Spring?@Conditional注解示例詳細(xì)講解,需要的朋友可以參考下
    2022-11-11
  • Idea中springboot項(xiàng)目的熱部署無法生效問題解決

    Idea中springboot項(xiàng)目的熱部署無法生效問題解決

    本文主要介紹了Idea中springboot項(xiàng)目的熱部署無法生效問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-10-10
  • java實(shí)現(xiàn)左旋轉(zhuǎn)字符串

    java實(shí)現(xiàn)左旋轉(zhuǎn)字符串

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)左旋轉(zhuǎn)字符串,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • SpringBoot3整合 Elasticsearch 8.x 使用Repository構(gòu)建增刪改查示例應(yīng)用

    SpringBoot3整合 Elasticsearch 8.x 使用Repository構(gòu)

    我們構(gòu)建了一個(gè)完整的 Spring Boot 3 和 Elasticsearch 8.x 的增刪改查示例應(yīng)用,使用 Spring Data Elasticsearch Repository,我們能夠快速實(shí)現(xiàn)對 Elasticsearch 的基本 CRUD 操作,簡化了開發(fā)流程,希望這個(gè)示例能夠幫助你理解如何在項(xiàng)目中有效使用 Elasticsearch!
    2024-11-11
  • Java執(zhí)行JS腳本工具

    Java執(zhí)行JS腳本工具

    今天小編就為大家分享一篇關(guān)于Java執(zhí)行JS腳本工具,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • Java反射機(jī)制如何解決數(shù)據(jù)傳值為空的問題

    Java反射機(jī)制如何解決數(shù)據(jù)傳值為空的問題

    這篇文章主要介紹了Java反射機(jī)制如何解決數(shù)據(jù)傳值為空的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java利用樸素貝葉斯分類算法實(shí)現(xiàn)信息分類

    Java利用樸素貝葉斯分類算法實(shí)現(xiàn)信息分類

    貝葉斯分類算法是統(tǒng)計(jì)學(xué)的一種分類方法,它是一類利用概率統(tǒng)計(jì)知識進(jìn)行分類的算法。本文將利用樸素貝葉斯分類算法實(shí)現(xiàn)信息分類,需要的可以參考一下
    2022-06-06
  • IDEA必備開發(fā)神器之EasyCode

    IDEA必備開發(fā)神器之EasyCode

    對于java程序員來說,日常工作中就是crud的操作,每次都要搭建MVC三層,還是很繁瑣,這里就出現(xiàn)了神器easycode的工具.可以快速生成代碼.并且還可以自定義模板.需要的朋友可以參考下
    2021-05-05
  • Java面向?qū)ο笾^承、構(gòu)造方法、重寫、重載

    Java面向?qū)ο笾^承、構(gòu)造方法、重寫、重載

    本章具體介紹了什么是構(gòu)造方法、繼承、重寫、重載以及創(chuàng)建方法,整篇文章用老司機(jī)和人類來舉例,圖解穿插代碼案例,需要的朋友可以參考下
    2023-03-03
  • 運(yùn)行SpringBoot項(xiàng)目請求響應(yīng)流程分析以及404和500報(bào)錯(cuò)的解決辦法

    運(yùn)行SpringBoot項(xiàng)目請求響應(yīng)流程分析以及404和500報(bào)錯(cuò)的解決辦法

    這篇文章主要介紹了運(yùn)行Spring Boot項(xiàng)目請求響應(yīng)流程分析以及404和500報(bào)錯(cuò)的解決辦法,文中通過代碼示例和圖文講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-12-12

最新評論