咱們知道讓線程阻塞除了能夠調用sleep方法,join方法還有wait方法,前兩個是屬於Tread的方法,而wait是屬於Object的方法,今天就來聊一聊wait的用法。java
先看一看wait的三個重載方法spa
public final void wait() throws InterruptedException
public final void wait(long timeout) throws InterruptedException
public final void wait(long timeout, int nanos) throws InterruptedException
第一個跟第三個方法最終調用的都是第二個方法,第一個方法至關於調用wait(0),0表示永遠不超時。一旦調用的對象的wait方法,那麼只有調用對象的notify或者notifyAll才能將其喚醒,或者阻塞時間達到了timeout時間也會自動喚醒。線程
每個對象都有一個跟它關聯的monitor,只有獲取到對象的monitor才能調用對象的wait方法和調用對象的notify和notifyAll方法。也就是說wait,notify,notifyAll都必須在對象的synchronized同步方法裏面調用
若是wait沒有在對象的synchronized同步塊裏面執行會拋出3d
java.lang.IllegalMonitorStateException
private Object lock = new Object(); public void block(){ try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.base/java.lang.Object.wait(Native Method) at java.base/java.lang.Object.wait(Object.java:326) at com.bzl.dp.eqpt.dev.TestWait.block(TestWait.java:28) at com.bzl.dp.eqpt.dev.TestWait.lambda$main$0(TestWait.java:14) at java.base/java.lang.Thread.run(Thread.java:835)
public static void main(String[] args) { TestWait tw = new TestWait(); Thread t1 = new Thread(() -> tw.block()); t1.start(); //短暫休眠以便讓block先執行 try { Thread.sleep(10L); } catch (InterruptedException e) { e.printStackTrace(); } tw.release(); } private Object lock = new Object(); public void block() { synchronized (lock) { try { System.out.println("before wait"); lock.wait(); System.out.println("after wait"); } catch (InterruptedException e) { e.printStackTrace(); } } } public void release() { synchronized (lock) { lock.notify(); System.out.println("after release"); } }
before wait after release after wait
具體流程以下:
首先咱們啓動了一個新的線程執行了lock的wait方法,而後在主線程去喚醒執行了wait的線程,爲了讓block方法先執行,這裏還短暫的休眠了一下子code
完整流程圖以下:對象
除了使用notify或notifyAll,還可使用interrupt方法來中斷wait,當使用interrupt中斷wait時,會拋出InterruptedException異常
代碼以下:blog
public static void main(String[] args) { TestInterrupt tw = new TestInterrupt(); Thread t1 = new Thread(() -> tw.block()); t1.start(); new Thread(() -> tw.interrupt(t1)).start(); } private Object lock = new Object(); public void block() { synchronized (lock) { try { System.out.println("before wait"); lock.wait(); System.out.println("after wait"); } catch (InterruptedException e) { System.out.println("Thread is interrupted"); e.printStackTrace(); } } } public void interrupt(Thread t) { try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock) { t.interrupt(); try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Interrupt the thread."); } }
運行結果:同步
before wait Interrupt the thread. Thread is interrupted java.lang.InterruptedException at java.base/java.lang.Object.wait(Native Method) at java.base/java.lang.Object.wait(Object.java:326) at com.bzl.dp.eqpt.dev.TestInterrupt.block(TestInterrupt.java:24) at com.bzl.dp.eqpt.dev.TestInterrupt.lambda$main$0(TestInterrupt.java:13) at java.base/java.lang.Thread.run(Thread.java:835)
具體流程以下:it
完成流程圖以下:io