作者:折纸
集体博客:https://www.zhezhi.press
记录菜鸡的成长之旅!
题目形容
咱们提供了一个类:
public class Foo { public void first() { print("first"); } public void second() { print("second"); } public void third() { print("third"); }}
三个不同的线程 A、B、C 将会共用一个Foo
实例。
- 一个将会调用
first()
办法 - 一个将会调用
second()
办法 - 还有一个将会调用
third()
办法
请设计批改程序,以确保second()
办法在first()
办法之后被执行,third()
办法在second()
办法之后被执行。
示例 1:
输出: [1,2,3]
输入: "firstsecondthird"
解释:
有三个线程会被异步启动。
输出 [1,2,3] 示意线程 A 将会调用 first() 办法,线程 B 将会调用 second() 办法,线程 C 将会调用 third() 办法。
正确的输入是 "firstsecondthird"。
示例 2:
输出: [1,3,2]
输入: "firstsecondthird"
解释:
输出 [1,3,2] 示意线程 A 将会调用 first() 办法,线程 B 将会调用 third() 办法,线程 C 将会调用 second() 办法。
正确的输入是 "firstsecondthird"。
提醒:
- 只管输出中的数字仿佛暗示了程序,然而咱们并不保障线程在操作系统中的调度程序。
- 你看到的输出格局次要是为了确保测试的全面性。
话不多说 间接上代码,简略温习一下Lock、synchronized、还有CountDownLatch、Semaphore、CyclicBarrier等工具类的应用
ReentrantLock + Condition
class Foo { ReentrantLock lock = new ReentrantLock(); Condition a = lock.newCondition(); Condition b = lock.newCondition(); Condition c = lock.newCondition(); private volatile int status = 1; public Foo() { } public void first(Runnable printFirst) throws InterruptedException { try{ lock.lock(); while(status!=1){ a.await(); } status = 2; printFirst.run(); b.signal(); }finally{ lock.unlock(); } // printFirst.run() outputs "first". Do not change or remove this line. } public void second(Runnable printSecond) throws InterruptedException { try{ lock.lock(); while(status!=2){ b.await(); } status = 3; printSecond.run(); c.signal(); }finally{ lock.unlock(); } // printSecond.run() outputs "second". Do not change or remove this line. } public void third(Runnable printThird) throws InterruptedException { try{ lock.lock(); while(status!=3){ c.await(); } status = 1; printThird.run(); a.signal(); }finally{ lock.unlock(); } // printThird.run() outputs "third". Do not change or remove this line. } }
LockSupport
class Foo { static Thread aThread = null,bThread = null,cThread = null; private volatile int status = 1; public Foo() { } public void first(Runnable printFirst) throws InterruptedException { aThread = Thread.currentThread(); printFirst.run(); status = 2; LockSupport.unpark(bThread); // printFirst.run() outputs "first". Do not change or remove this line. // printFirst.run(); } public void second(Runnable printSecond) throws InterruptedException { bThread = Thread.currentThread(); while(status!=2) LockSupport.park(); printSecond.run(); status = 3; LockSupport.unpark(cThread); // printSecond.run() outputs "second". Do not change or remove this line. // printSecond.run(); } public void third(Runnable printThird) throws InterruptedException { cThread = Thread.currentThread(); while(status!=3) LockSupport.park(); printThird.run(); status = 1; LockSupport.unpark(aThread); // printThird.run() outputs "third". Do not change or remove this line. // printThird.run(); }}
synchronized + wait/notify
class Foo { Object lock = new Object(); private volatile int status = 1; public Foo() { } public void first(Runnable printFirst) throws InterruptedException { synchronized(lock){ while(status!=1){ lock.wait(); } printFirst.run(); status = 2; lock.notifyAll(); } // printFirst.run() outputs "first". Do not change or remove this line. } public void second(Runnable printSecond) throws InterruptedException { synchronized(lock){ while(status!=2){ lock.wait(); } printSecond.run(); status = 3; lock.notifyAll(); } // printSecond.run() outputs "second". Do not change or remove this line. } public void third(Runnable printThird) throws InterruptedException { synchronized(lock){ while(status!=3){ lock.wait(); } printThird.run(); status = 1; lock.notifyAll(); } // printThird.run() outputs "third". Do not change or remove this line. }}
Semaphore
class Foo { Semaphore s = new Semaphore(1); private volatile int status = 1; public Foo() { } public void first(Runnable printFirst) throws InterruptedException { while(status!=1){ } s.acquire(); // printFirst.run() outputs "first". Do not change or remove this line. printFirst.run(); status = 2; s.release(); } public void second(Runnable printSecond) throws InterruptedException { while(status!=2){ } s.acquire(); // printFirst.run() outputs "first". Do not change or remove this line. printSecond.run(); status = 3; s.release(); // printSecond.run() outputs "second". Do not change or remove this line. } public void third(Runnable printThird) throws InterruptedException { while(status!=3){ } s.acquire(); // printFirst.run() outputs "first". Do not change or remove this line. printThird.run(); status = 1; s.release(); // printThird.run() outputs "third". Do not change or remove this line. }}
CountDownLatch
class Foo { CountDownLatch aLatch = new CountDownLatch(1); CountDownLatch bLatch = new CountDownLatch(1); public Foo() { } public void first(Runnable printFirst) throws InterruptedException { // printFirst.run() outputs "first". Do not change or remove this line. printFirst.run(); aLatch.countDown(); } public void second(Runnable printSecond) throws InterruptedException { aLatch.await();//aLatch计数器为1,当线程1打印结束后--为0,这里不再被阻塞 线程2开始打印 // printSecond.run() outputs "second". Do not change or remove this line. printSecond.run(); bLatch.countDown(); } public void third(Runnable printThird) throws InterruptedException { bLatch.await();//bLatch计数器为1,当线程1打印结束后--为0,这里不再被阻塞 线程2开始打印 // printThird.run() outputs "third". Do not change or remove this line. printThird.run(); }}
CyclicBarrier
class Foo { CyclicBarrier cy1 = new CyclicBarrier(2); CyclicBarrier cy2 = new CyclicBarrier(2); public Foo() { } public void first(Runnable printFirst) throws InterruptedException { // printFirst.run() outputs "first". Do not change or remove this line. printFirst.run(); try{ cy1.await(); }catch(BrokenBarrierException e){ e.printStackTrace(); } } public void second(Runnable printSecond) throws InterruptedException { try{ cy1.await(); //线程1曾经通过了cy1示意线程1曾经打印结束//当线程1 和2都达到此处后 线程2才开始打印 printSecond.run(); cy2.await();//线程2达到屏障2 }catch(BrokenBarrierException e){ e.printStackTrace(); } // printSecond.run() outputs "second". Do not change or remove this line. } public void third(Runnable printThird) throws InterruptedException { try{ cy2.await();//线程2打印结束后线程3才开始打印 printThird.run(); }catch(BrokenBarrierException e){ e.printStackTrace(); } // printThird.run() outputs "third". Do not change or remove this line. }}