代碼演示
package com.dwz.concurrency2.chapter2; import java.util.stream.IntStream; /** * 1.所有的對象都會有一個wait set,用來存放調用了該對象wait方法之后進入block狀態的線程 * 2.線程被notify之后,不一定立即得到執行 * 3.線程從wait set中被喚醒的順序不一定是FIFO * 4.線程被喚醒后,必須重新去獲取鎖,會記錄之前wait的位置,在wait的位置繼續往下執行 */ public class WaitSet { private static final Object LOCK = new Object(); private static void work() { synchronized (LOCK) { System.out.println("begin..."); try { System.out.println("Thread will come in."); LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread will out."); } }
}
測試一:驗證線程從wait set中被喚醒的順序不一定是FIFO
IntStream.rangeClosed(1, 10).forEach(i-> new Thread(String.valueOf(i)) { @Override public void run() { synchronized (LOCK) { try { System.out.println(Thread.currentThread().getName() + " will come to wait set."); LOCK.wait(); System.err.println(Thread.currentThread().getName() + " will leave to wait set."); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start() ); Thread.sleep(3000); IntStream.rangeClosed(1, 10).forEach(i-> { synchronized (LOCK) { LOCK.notify(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } );
測試二:驗證線程被喚醒后,必須重新去獲取鎖,會記錄之前wait的位置,在wait的位置繼續往下執行
new Thread() { @Override public void run() { work(); } }.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (LOCK) { LOCK.notifyAll(); }
注意:線程不能進行自我喚醒,必須由其它線程喚醒