leetcode.1114-按序打印-多线程案例

简介: leetcode.1114-按序打印-多线程案例

题目


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,如果是,则进入方法,否则空转。


1. class Foo {
2. 
3. private AtomicInteger firstJobDone = new AtomicInteger(0);
4. private AtomicInteger secondJobDone = new AtomicInteger(0);
5. 
6. public Foo() {}
7. 
8. public void first(Runnable printFirst) throws InterruptedException {
9. // printFirst.run() outputs "first".
10.     printFirst.run();
11. // mark the first job as done, by increasing its count.
12.     firstJobDone.incrementAndGet();
13.   }
14. 
15. public void second(Runnable printSecond) throws InterruptedException {
16. while (firstJobDone.get() != 1) {
17. // waiting for the first job to be done.
18.     }
19. // printSecond.run() outputs "second".
20.     printSecond.run();
21. // mark the second as done, by increasing its count.
22.     secondJobDone.incrementAndGet();
23.   }
24. 
25. public void third(Runnable printThird) throws InterruptedException {
26. while (secondJobDone.get() != 1) {
27. // waiting for the second job to be done.
28.     }
29. // printThird.run() outputs "third".
30.     printThird.run();
31.   }
32. }
33.

方法二


CountDownLatch(int count); //构造方法,创建一个值为count 的计数器。


//阻塞当前线程,将当前线程加入阻塞队列

//当计数器的值变为0时,在CountDownLatch上await()的线程就会被唤醒

await();


await(long timeout, TimeUnit unit);//在timeout的时间之内阻塞当前线程,时间一过则当前线程可以执行,


countDown();//对计数器进行递减1操作,当计数器递减至0时,当前线程会去唤醒阻塞队列里的所有线程。

在构造函数中使用 CountDownLatch()来说设置两个值为1的计数器,然后在second和third函数中加入awati()函数进行等待,当计数器为0时被唤醒

代码:


1. class Foo {
2. 
3. private final CountDownLatch firstDone;
4. private final CountDownLatch secondDone;
5. 
6. public Foo() {
7.         firstDone = new CountDownLatch(1);
8.         secondDone = new CountDownLatch(1);
9.     }
10. 
11. public void first(Runnable printFirst) throws InterruptedException {
12. // printFirst.run() outputs "first". Do not change or remove this line.
13.         printFirst.run();
14.         firstDone.countDown();
15.     }
16. 
17. public void second(Runnable printSecond) throws InterruptedException {
18.         firstDone.await();
19. // printSecond.run() outputs "second". Do not change or remove this line.
20.         printSecond.run();
21.         secondDone.countDown();
22.     }
23. 
24. public void third(Runnable printThird) throws InterruptedException {
25.         secondDone.await();
26. // printThird.run() outputs "third". Do not change or remove this line.
27.         printThird.run();
28.     }
29. }

方法三


使用信号量Semaphore ,先初始化信号量,不允许second和third函数运行,在first函数末尾调用release函数使得计数值加一,second函数可以运行;同理,在second函数结束后调用release函数增肌计数值,使得third()函数可以运行。


1. class Foo {
2. 
3. private Semaphore two = new Semaphore(0);
4. private Semaphore three = new Semaphore(0);
5. 
6. public Foo() {
7. 
8.     }
9. 
10. public void first(Runnable printFirst) throws InterruptedException {
11. 
12. // printFirst.run() outputs "first". Do not change or remove this line.
13.         printFirst.run();
14.         two.release();
15.     }
16. 
17. public void second(Runnable printSecond) throws InterruptedException {
18.         two.acquire();
19. // printSecond.run() outputs "second". Do not change or remove this line.
20.         printSecond.run();
21.         three.release();
22.     }
23. 
24. public void third(Runnable printThird) throws InterruptedException {
25.         three.acquire();
26. // printThird.run() outputs "third". Do not change or remove this line.
27.         printThird.run();
28.     }
29. }

方法四


使用object和synchronized进行原子操作


1. public class Foo {
2. private  int flag = 1;
3. private final Object object = new Object();
4. 
5. public Foo() {
6. 
7.     }
8. 
9. public void first(Runnable printFirst) throws InterruptedException {
10. synchronized (object) {
11. while (flag != 1) object.wait();
12.             printFirst.run();
13.             flag = 2;
14.             object.notifyAll();
15.         }
16.     }
17. 
18. public void second(Runnable printSecond) throws InterruptedException {
19. synchronized (object) {
20. while (flag != 2) object.wait();
21.             printSecond.run();
22.             flag = 3;
23.             object.notifyAll();
24.         }
25.     }
26. 
27. public void third(Runnable printThird) throws InterruptedException {
28. synchronized (object) {
29. while (flag != 3) object.wait();
30.             printThird.run();
31.         }
32. 
33.     }
34. }
目录
相关文章
|
2月前
多线程案例-定时器(附完整代码)
多线程案例-定时器(附完整代码)
262 0
|
2月前
|
设计模式 监控 Java
Java多线程基础-11:工厂模式及代码案例之线程池(一)
本文介绍了Java并发框架中的线程池工具,特别是`java.util.concurrent`包中的`Executors`和`ThreadPoolExecutor`类。线程池通过预先创建并管理一组线程,可以提高多线程任务的效率和响应速度,减少线程创建和销毁的开销。
47 2
|
2月前
|
安全 Java
Java多线程基础-10:代码案例之定时器(一)
`Timer` 是 Java 中的一个定时器类,用于在指定延迟后执行指定的任务。它常用于实现定时任务,例如在网络通信中设置超时或定期清理数据。`Timer` 的核心方法是 `schedule()`,它可以安排任务在延迟一段时间后执行。`
60 1
|
2月前
|
Java Python 开发者
Python 学习之路 01基础入门---【Python安装,Python程序基本组成】
线程池详解与异步任务编排使用案例-xian-cheng-chi-xiang-jie-yu-yi-bu-ren-wu-bian-pai-shi-yong-an-li
486 3
Python 学习之路 01基础入门---【Python安装,Python程序基本组成】
|
2月前
|
SQL Dubbo Java
案例分析|线程池相关故障梳理&总结
本文作者梳理和分享了线程池类的故障,分别从故障视角和技术视角两个角度来分析总结,故障视角可以看到现象和教训,而技术视角可以透过现象看到本质更进一步可以看看如何避免。
84696 136
案例分析|线程池相关故障梳理&总结
|
2月前
|
Python
Python学习之路 02 之分支结构
Python学习之路 02 之分支结构
469 0
Python学习之路 02 之分支结构
|
2月前
|
Java
线程池详解与异步任务编排使用案例-xian-cheng-chi-xiang-jie-yu-yi-bu-ren-wu-bian-pai-shi-yong-an-li
线程池详解与异步任务编排使用案例-xian-cheng-chi-xiang-jie-yu-yi-bu-ren-wu-bian-pai-shi-yong-an-li
57 0
|
2月前
|
设计模式 安全 Java
多线程(代码案例: 单例模式, 阻塞队列, 生产者消费者模型,定时器)
多线程(代码案例: 单例模式, 阻塞队列, 生产者消费者模型,定时器)
29 2
|
2月前
|
设计模式 安全 Java
Java多线程案例-Java多线程(3)
Java多线程案例-Java多线程(3)
15 1
|
2月前
|
存储 Java 调度
Java多线程基础-11:工厂模式及代码案例之线程池(二)
这篇内容介绍了Java多线程基础,特别是线程池中的定时器和拒绝策略。
30 0