| 特性 | Thread.yield() | Thread.sleep(millis) |
|---|---|---|
| 方法性質 | 靜態原生方法,提示調度器 | 靜態原生方法,強制阻塞 |
| 狀態轉換 | RUNNABLE → RUNNABLE(可能立即再次獲取 CPU) | RUNNABLE → TIMED_WAITING → RUNNABLE |
| 釋放鎖 | 不釋放 任何鎖(synchronized/Lock) | 不釋放 任何鎖 |
| 時間精度 | 無時間參數,完全依賴調度器 | 毫秒/納秒級參數,盡力保證最小睡眠時間 |
| 中斷響應 | 不可中斷 | 可中斷,拋出 InterruptedException |
| 典型用途 | 長時間計算主動讓步、測試併發 | 定時任務、節流、模擬延遲、協作式等待 |
public static native void yield();
HotSpot JVM 實現中,yield() 最終調用 OS 調度接口(Linux: sched_yield(),Windows: SwitchToThread())。
public class YieldDemo {
static volatile int count = 0;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000000; i++) count++;
}, "NoYield");
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000000; i++) {
count++;
Thread.yield(); // 主動讓步
}
}, "WithYield");
t1.start(); t2.start();
// t2 執行時間顯著 > t1,但不保證絕對公平
}
}
public static native void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos) throws InterruptedException;
interrupt() 中斷,拋出 InterruptedException(會清除中斷標誌)try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// 1. 記錄日誌
log.warn("睡眠被中斷", e);
// 2. 重新設置中斷標誌(關鍵!調用棧上層需感知)
Thread.currentThread().interrupt();
// 3. 退出/拋出/恢復邏輯
return; // 或 throw new RuntimeException(e);
}
-XX:+UseMembar 影響:可能 10-15ms 粒度sleep(0) 相當於 yield()(部分 JVM 優化)Object lock = new Object();
Thread holder = new Thread(() -> {
synchronized (lock) {
System.out.println("持有鎖,開始 sleep 2秒");
try { Thread.sleep(2000); } catch (InterruptedException e) {}
System.out.println("睡眠結束,釋放鎖");
}
}, "Holder");
Thread waiter = new Thread(() -> {
try { Thread.sleep(500); } catch (InterruptedException e) {} // 確保 holder 先拿鎖
System.out.println("嘗試獲取鎖...");
synchronized (lock) {
System.out.println("獲取鎖成功");
}
}, "Waiter");
holder.start();
waiter.start();
// 輸出證明:sleep 期間鎖未釋放,waiter 必須等待 2 秒
// 若 holder 用 yield() 替代 sleep:
// waiter 幾乎立即獲取鎖(yield 不阻塞,holder 仍在同步塊內快速輪轉)
| 需求 | 推薦方案 | 理由 |
|---|---|---|
| 高精度定時/周期任務 | ScheduledExecutorService | 線程池管理、異常處理、關閉控制 |
| 可中斷的限時等待鎖 | lock.tryLock(timeout, unit) | 釋放鎖、響應中斷、精確超時控制 |
| 條件等待(生產者消費者) | Condition.await(timeout) | 釋放鎖、精準喚醒、支持多條件 |
| 虛擬線程友好睡眠 | Thread.sleep() (JDK 21+) | 虛擬線程 sleep 釋放載體線程,不阻塞平台線程 |
| 長計算主動讓步 | 重構為短任務提交線程池 | yield 不可控,任務分片更優雅 |
yield() 讓出 CPU 給低優先級線程 → 錯,調度器通常只考慮同優先級或更高sleep() 釋放鎖 → 錯,持有鎖 sleep 會導致其他線程饑餓sleep(1000) 精確 1 秒 → 不保證,受系統調度、GC、負載影響,僅保證至少 1 秒yield() 可替代 sleep(1) → 語義不同,yield 不進入 WAITING,不計入睡眠統計Thread.sleep() 變為「非阻塞掛起」,大幅提升吞吐yield() 是禮讓提示(RUNNABLE→RUNNABLE,不釋放鎖、不可中斷、不可控);sleep() 是定時阻塞(RUNNABLE→TIMED_WAITING→RUNNABLE,不釋放鎖、可中斷、有時間參數)。核心共同點:**均不釋放鎖**。實戰中極少直接使用 yield(),sleep() 僅用於簡單延遲/測試,生產環境定時/等待請用 ScheduledExecutorService、Lock.tryLock、Condition.await 等高級並發工具。