被面试是一种狠高效的学习方式。
前几天被人面试问到了,我当时直接说用CountDownLatch(后面就呵呵了...)后来阅读了点资料,仔细想了想总结如下。
古老的wait notify
下面是一个报错的例子。其实完全可以用这种古老的wait notify方式实现。可能用法不太对,欢迎指正。
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 1sjava.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()实现
也可以用Thread.join()实现。书上说,这个方法会等待线程完成后再执行,里面是个循环等待。“直到线程join中止后,线程的this.notifyAll会调用....” 代码如下,不用加监视器也不会报错
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 1sawake ... finishThreadJoinTest.main().....wait inner class down
CountDownLatch实现
这个属于JUC的工具类,从1.5开始。主要用到方法是countDown() 和 await()。 await()方法阻塞当前线程,直到计数器等于0; countDown()方法将计数器减一;
代码如下:
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(); } }}