public class Foo { public void one() { print(“one”); } public void two() { print(“two”); } public void three() { print(“three”); } } 三个不同的线程将会共用一个 Foo 实例。
线程 A 将会调用 one() 方法 线程 B 将会调用 two() 方法 线程 C 将会调用 three() 方法 请设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。
classFoo{
boolean firstFinished = false; boolean secondFinished = false; final Object obj = new Object();
publicFoo(){
}
publicvoidfirst(Runnable printFirst)throws InterruptedException { synchronized (obj) { // printFirst.run() outputs "first". Do not change or remove this line. printFirst.run(); firstFinished = true; } }
publicvoidsecond(Runnable printSecond)throws InterruptedException { synchronized (obj) { while (firstFinished) { // printSecond.run() outputs "second". Do not change or remove this line. printSecond.run(); secondFinished = true; }
} }
publicvoidthird(Runnable printThird)throws InterruptedException { synchronized (obj) { while (secondFinished) { // printThird.run() outputs "third". Do not change or remove this line. printThird.run(); } } } }
提交结果:超时
原因:while循环,不停抢占CPU资源来判断自身是否结束循环(自旋)。
优化
使用wait+notify避免了自旋
classFoo{
final Object obj = new Object(); boolean firstFinished = false; boolean secondFinished = false;
publicFoo(){
}
publicvoidfirst(Runnable printFirst)throws InterruptedException { synchronized (obj) { // printFirst.run() outputs "first". Do not change or remove this line. printFirst.run(); firstFinished = true; obj.notifyAll(); } }
publicvoidsecond(Runnable printSecond)throws InterruptedException { synchronized (obj) { while (!firstFinished) { obj.wait(); } // printSecond.run() outputs "second". Do not change or remove this line. printSecond.run(); secondFinished = true; obj.notifyAll(); } }
publicvoidthird(Runnable printThird)throws InterruptedException { synchronized (obj) { while (!secondFinished) { obj.wait(); } // printThird.run() outputs "third". Do not change or remove this line. printThird.run(); } } }
优化:使用CountDownLatch(Semaphore同理)
classFoo{
CountDownLatch c2; CountDownLatch c3;
publicFoo(){ c2 = new CountDownLatch(1); c3 = new CountDownLatch(1); }
publicvoidfirst(Runnable printFirst)throws InterruptedException { // printFirst.run() outputs "first". Do not change or remove this line. printFirst.run(); c2.countDown(); }
publicvoidsecond(Runnable printSecond)throws InterruptedException { c2.await(); // printSecond.run() outputs "second". Do not change or remove this line. printSecond.run(); c3.countDown(); }
publicvoidthird(Runnable printThird)throws InterruptedException { c3.await(); // printThird.run() outputs "third". Do not change or remove this line. printThird.run(); } }