被面試是一種狠高效的學習方式。java
前幾天被人面試問到了,我當時直接說用CountDownLatch(後面就呵呵了...)後來閱讀了點資料,仔細想了想總結以下。面試
下面是一個報錯的例子。其實徹底能夠用這種古老的wait notify方式實現。可能用法不太對,歡迎指正。ide
public class ThreadANTest { public static void main(String[] args) throws InterruptedException { InnerClass ic = new InnerClass(); ic.start(); //註釋掉這個會報錯。。。。 //synchronized (ic) { ic.wait(); System.out.println("main...."); //} } public static class InnerClass extends Thread{ @Override public void run() { //註釋掉這個會報錯。。。。 //synchronized (this) { System.out.println("ThreadANTest.InnerClass.run()"); System.out.println("sleep 1s"); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("awake ... finish"); this.notify(); //} } } }
報錯信息以下,大體意思是沒有加監視器工具
Exception in thread "main" ThreadANTest.InnerClass.run() sleep 1s java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Unknown Source) at com.thread.ThreadANTest.main(ThreadANTest.java:10) awake ... finishException in thread "Thread-0" java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at com.thread.ThreadANTest$InnerClass.run(ThreadANTest.java:31)
解決辦法就是,把註釋放開加上監視器就行了。學習
也能夠用Thread.join()實現。書上說,這個方法會等待線程完成後再執行,裏面是個循環等待。「直到線程join停止後,線程的this.notifyAll會調用....」 代碼以下,不用加監視器也不會報錯this
public class ThreadJoinTest { public static void main(String[] args) throws InterruptedException { InnerClass inner = new InnerClass(); inner.start(); inner.join(); System.out.println("ThreadJoinTest.main().....wait inner class down"); } public static class InnerClass extends Thread{ @Override public void run() { System.out.println("ThreadJoinTest.InnerClass.run()"); System.out.println("sleep 1s"); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("awake ... finish"); } } }
輸出結果以下:線程
ThreadJoinTest.InnerClass.run() sleep 1s awake ... finish ThreadJoinTest.main().....wait inner class down
這個屬於JUC的工具類,從1.5開始。主要用到方法是countDown() 和 await()。 await()方法阻塞當前線程,直到計數器等於0; countDown()方法將計數器減一;code
代碼以下:it
import java.util.concurrent.CountDownLatch; public class CountDownLatchTest { public static void main(String[] args) throws InterruptedException { CountDownLatch cdl = new CountDownLatch(2); InnerClass ic = new InnerClass(cdl); ic.start(); cdl.await(); System.out.println("CountDownLatchTest.main()"); } public static class InnerClass extends Thread{ private CountDownLatch cdl; public InnerClass(CountDownLatch cdl){ this.cdl = cdl; } @Override public void run() { System.out.println(1); cdl.countDown(); System.out.println(2); cdl.countDown(); } } }