作者:折纸
集体博客: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.}
}