首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 線程協作詳解:join()、sleep()、yield() 與 wait() 的區別與應用

     編輯:Java 綜合教學

Java 線程協作機制深度解析

線程阻塞是並發編程的核心概念。本文系統講解 join()、sleep()、yield()、wait() 四種讓線程暫停執行的方法,並重點分析 join() 的實現原理與應用場景。

一、線程阻塞的兩大原因

  1. 數據依賴:當前線程需要另一線程的執行結果,必須等待其完成。
  2. 資源競爭:多線程訪問共享資源,未獲同步鎖而進入阻塞。

二、阻塞狀態本質

阻塞線程不佔用 CPU,調度器忽略它,直到條件滿足轉為就緒狀態,爭奪時間片才能繼續運行。

三、四大方法對比

方法所屬類釋放鎖典型場景
join()Thread否等待子線程結束,獲取其結果
sleep()Thread否定時暫停,不涉及同步
yield()Thread否主動讓出 CPU,重新競爭
wait()Object是同步塊中等待通知,配合 notify/notifyAll

四、join() 核心解析

1. 方法簽名

public final void join() throws InterruptedException { join(0); }
public final synchronized void join(long millis) throws InterruptedException
  • join():無限等待目標線程終止。
  • join(long millis):限時等待,超時後繼續執行。

2. 實戰示例

public class ThreadJoinTest {
    private static String str = null;

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                System.out.println("進入 " + Thread.currentThread().getName() + " 線程");
                Thread.sleep(1000);
                str = "hello World";
                System.out.println(Thread.currentThread().getName() + " 線程業務處理完畢");
            } catch (InterruptedException e) { e.printStackTrace(); }
        });
        thread.start();

        try {
            // thread.join(); // 取消註釋觀察差異
            System.out.println(Thread.currentThread().getName() + " 線程處理業務開始");
            System.out.println("獲取 str 值:" + str);
        } catch (Exception e) { e.printStackTrace(); }
    }
}

未調用 join() 輸出:

main 線程處理業務開始
進入 Thread-0 線程
獲取 str 值:null
Thread-0 線程業務處理完畢

調用 join() 輸出:

main 線程處理業務開始
進入 Thread-0 線程
Thread-0 線程業務處理完畢
獲取 str 值:hello World

調用 join(100) 輸出: 等待 100ms 不夠,str 仍為 null。

3. 源碼實現原理

public final synchronized void join(long millis) throws InterruptedException {
    long base = System.currentTimeMillis();
    long now = 0;
    if (millis < 0) throw new IllegalArgumentException("timeout value is negative");
    if (millis == 0) {
        while (isAlive()) wait(0);
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) break;
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

本質:調用線程在目標線程對象監視器上 wait(),目標線程終止前 JVM 自動調用 notifyAll() 喚醒等待者。

五、總結

join() 是線程間同步的輕量級手段,適用於「主線程依賴子線程結果」的場景。理解其底層使用 wait/notify 機制,有助於排查死鎖與超時問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved