被面试是一种狠高效的学习方式。
前几天被人面试问到了,我当时直接说用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 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()实现
也可以用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 1s
awake ... finish
ThreadJoinTest.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();
}
}
}