leetcode.1114-按序打印-多线程案例
创始人
2025-06-01 02:14:35

题目

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();}}
}

相关内容

热门资讯

云龙天池国家级自然保护区入选世... 转自:云南日报记者近日从云龙天池国家级自然保护区获悉,该保护区正式入选世界自然保护联盟绿色名录,成为...
芒果干里的“暖心账”​ 我 为 群 众 办 实 事我是楚雄彝族自治州楚雄市八角镇大麦地村委会泥期苴小组的鲁晓玲。天还没亮,新...
在亲戚借条上签名被判连带清偿责...   三湘都市报12月14日讯  欠钱逾期未还,双方公堂对簿,竟因借据上的“担保人”“连带担保人”起了...
学分能换“高级工”证书?湖南暂...   毕业就能拿到“高级工”的技能证书,实现“毕业即持证”,这是种什么样的体验?近日,安徽皖江工学院土...
长赣高铁湖南段首座隧道进洞施工     12月13日,位于浏阳市荷花街道和澄潭江镇的长赣高铁湖南段首座隧道——苏家庵隧道正式进洞。 ...