1114. 按序打印 - 力扣(Leetcode)
给你一个类:
public class Foo {public void first() { print("first"); }public void second() { print("second"); }public void third() { print("third"); } }三个不同的线程 A、B、C 将会共用一个
Foo实例。
- 线程 A 将会调用
first()方法- 线程 B 将会调用
second()方法- 线程 C 将会调用
third()方法请设计修改程序,以确保
second()方法在first()方法之后被执行,third()方法在second()方法之后被执行。提示:
- 尽管输入中的数字似乎暗示了顺序,但是我们并不保证线程在操作系统中的调度顺序。
- 你看到的输入格式主要是为了确保测试的全面性。
先声明两个AtomicInteger变量并初始化为0,使用他来控制first()和second(),second() 和third()之间的顺序关系。
在进入second和third方法时,提前进入循环去检验变量是否被增加为1,如果是,则进入方法,否则空转。
class Foo {private AtomicInteger firstJobDone = new AtomicInteger(0);private AtomicInteger secondJobDone = new AtomicInteger(0);public Foo() {}public void first(Runnable printFirst) throws InterruptedException {// printFirst.run() outputs "first".printFirst.run();// mark the first job as done, by increasing its count.firstJobDone.incrementAndGet();}public void second(Runnable printSecond) throws InterruptedException {while (firstJobDone.get() != 1) {// waiting for the first job to be done.}// printSecond.run() outputs "second".printSecond.run();// mark the second as done, by increasing its count.secondJobDone.incrementAndGet();}public void third(Runnable printThird) throws InterruptedException {while (secondJobDone.get() != 1) {// waiting for the second job to be done.}// printThird.run() outputs "third".printThird.run();}
}
CountDownLatch(int count); //构造方法,创建一个值为count 的计数器。
//阻塞当前线程,将当前线程加入阻塞队列。
//当计数器的值变为0时,在CountDownLatch上await()的线程就会被唤醒
await();
await(long timeout, TimeUnit unit);//在timeout的时间之内阻塞当前线程,时间一过则当前线程可以执行,
countDown();//对计数器进行递减1操作,当计数器递减至0时,当前线程会去唤醒阻塞队列里的所有线程。
在构造函数中使用 CountDownLatch()来说设置两个值为1的计数器,然后在second和third函数中加入awati()函数进行等待,当计数器为0时被唤醒
代码:
class Foo {private final CountDownLatch firstDone;private final CountDownLatch secondDone;public Foo() {firstDone = new CountDownLatch(1);secondDone = new CountDownLatch(1);}public void first(Runnable printFirst) throws InterruptedException {// printFirst.run() outputs "first". Do not change or remove this line.printFirst.run();firstDone.countDown();}public void second(Runnable printSecond) throws InterruptedException {firstDone.await();// printSecond.run() outputs "second". Do not change or remove this line.printSecond.run();secondDone.countDown();}public void third(Runnable printThird) throws InterruptedException {secondDone.await();// printThird.run() outputs "third". Do not change or remove this line.printThird.run();}
}
使用信号量Semaphore ,先初始化信号量,不允许second和third函数运行,在first函数末尾调用release函数使得计数值加一,second函数可以运行;同理,在second函数结束后调用release函数增肌计数值,使得third()函数可以运行。
class Foo {private Semaphore two = new Semaphore(0);private Semaphore three = new Semaphore(0);public Foo() {}public void first(Runnable printFirst) throws InterruptedException {// printFirst.run() outputs "first". Do not change or remove this line.printFirst.run();two.release();}public void second(Runnable printSecond) throws InterruptedException {two.acquire();// printSecond.run() outputs "second". Do not change or remove this line.printSecond.run();three.release();}public void third(Runnable printThird) throws InterruptedException {three.acquire();// printThird.run() outputs "third". Do not change or remove this line.printThird.run();}
}
使用object和synchronized进行原子操作
public class Foo {private int flag = 1;private final Object object = new Object();public Foo() {}public void first(Runnable printFirst) throws InterruptedException {synchronized (object) {while (flag != 1) object.wait();printFirst.run();flag = 2;object.notifyAll();}}public void second(Runnable printSecond) throws InterruptedException {synchronized (object) {while (flag != 2) object.wait();printSecond.run();flag = 3;object.notifyAll();}}public void third(Runnable printThird) throws InterruptedException {synchronized (object) {while (flag != 3) object.wait();printThird.run();}}
}