一、sleep() 與 wait()
兩者都會讓當前線程進入等待狀態。喚醒后都需要等待 CPU 資源,不一定會立即執行。若在等待期間被調用此線程的的 interrupt() 方法,將會產生 InterruptedException 異常。
wait() 是 Object 類的方法,會釋放對象鎖,並讓出 CPU 資源。只能在 synchronized 下使用,使用 notify() 或 notiftAll() 喚醒。

// 線程工廠,這里主要用來設置線程名字 ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build(); // 創建線程池 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(6, 6, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); Object object = new Object(); threadPool.execute(() -> { try { synchronized (object) { object.wait(); System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAA"); } } catch (InterruptedException e) { e.printStackTrace(); } }); threadPool.execute(() -> { synchronized (object) { System.out.println("BBBBBBBBBBBBBBBBBBBBBBBBBBB"); object.notify(); } });
sleep() 是 Thread 類的靜態方法,只會讓出 CPU 資源。可以使低優先級的線程得到執行的機會。

// 線程工廠,這里主要用來設置線程名字 ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build(); // 創建線程池 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(6, 6, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); threadPool.execute(() -> { try { // 阻塞 1 秒 Thread.sleep(1000); System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAA"); } catch (InterruptedException e) { e.printStackTrace(); } }); threadPool.execute(() -> { System.out.println("BBBBBBBBBBBBBBBBBBBBBBBBBBBB"); });
兩個示例都保證了 B 會在 A 之前被打印
二、notify() 與 notifyAll()
與 wait() 配合使用。兩者都會喚醒其他線程,且會釋放對象鎖,不會阻塞當前線程。
其中 notify() 只喚醒等待線程當中的一個,notifyAll() 會喚醒所有等待線程。
notify() 是隨機喚醒的,不同的 JDK 版本,在等待隊列中喚醒的線程,其位置在等待隊列中不同。
JDK1.8 中 notify() 喚醒的是等待隊列中的頭節點,即等待時間最長的那個線程。
喚醒的線程為同一個對象鎖的線程。喚醒一個或所有,都只有一個線程會獲取到鎖對象。
三、yield() 與 join()
yield() 是 Thread 類的靜態原生 (native) 方法,作用是讓出 CPU 資源,不會阻塞當前線程,但可能讓出 CPU 資源后,系統重新調度后又會選擇給該線程 CPU 資源。使用場景比較少。
join() 是Thread 類實例的方法,可以使得一個線程在另一個線程結束后再執行。當前運行的線程將進入到等待狀態直到另一個線程執行完成。

Thread t1 = new Thread(){ @Override public void run() { try { Thread.sleep(1000); System.out.println("A"); } catch (InterruptedException e) { e.printStackTrace(); } } }; Thread t2 = new Thread(){ @Override public void run() { try { t1.join(); System.out.println("B"); } catch (InterruptedException e) { e.printStackTrace(); } } }; t2.start(); t1.start();
示例中保證了 A 在 B 之前被打印
四、interrupt()
中斷等待狀態的線程,並拋出異常。相關方法有三個。
interrupt() 是 Thread 類實例的方法,給線程中斷狀態設置為 false,等線程進入到等待狀態時就會被中斷,並拋出異常
isInterrupted() 是 Thread 類實例的方法,檢測線程的中斷狀態
interrupted() 是 Thread 類的靜態方法,實質調用的是 currentThread().isInterrupted(true),作用是檢測線程的中斷狀態,然后將狀態設置為 true

Thread t1 = new Thread() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + "啟動后的中斷狀態:" + Thread.currentThread().isInterrupted()); Thread.currentThread().interrupt(); System.out.println(Thread.currentThread().getName() + "interrupt()后的中斷狀態:" + Thread.currentThread().isInterrupted()); System.out.println(Thread.currentThread().getName() + "isInterrupted()獲取中斷狀態:" + Thread.interrupted()); System.out.println(Thread.currentThread().getName() + "interrupted()后的中斷狀態:" + Thread.currentThread().isInterrupted()); Thread.currentThread().interrupt(); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); System.out.println(Thread.currentThread().getName() + "異常時中斷狀態:" + Thread.interrupted()); } } }; new Thread() { @Override public void run() { System.out.println(t1.getName() + "未啟動時的中斷狀態:" + t1.isInterrupted()); System.out.println("======================================================="); t1.start(); try { t1.join(); System.out.println("======================================================="); System.out.println(t1.getName() + "執行完時的中斷狀態:" + t1.isInterrupted()); } catch (InterruptedException e) { e.printStackTrace(); } } }.start();
https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html