1114. 按序打印
题目描述
给你一个类:
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()
方法之后被执行。
提示:
- 尽管输入中的数字似乎暗示了顺序,但是我们并不保证线程在操作系统中的调度顺序。
- 你看到的输入格式主要是为了确保测试的全面性。
示例 1:
输入:nums = [1,2,3] 输出:"firstsecondthird" 解释: 有三个线程会被异步启动。输入 [1,2,3] 表示线程 A 将会调用 first() 方法,线程 B 将会调用 second() 方法,线程 C 将会调用 third() 方法。正确的输出是 "firstsecondthird"。
示例 2:
输入:nums = [1,3,2] 输出:"firstsecondthird" 解释: 输入 [1,3,2] 表示线程 A 将会调用 first() 方法,线程 B 将会调用 third() 方法,线程 C 将会调用 second() 方法。正确的输出是 "firstsecondthird"。
提示:
nums
是[1, 2, 3]
的一组排列
解法
方法一:多线程 + 锁或信号量
我们可以用三个信号量 \(a\), \(b\), \(c\) 来控制三个线程的执行顺序,初始时 \(a\) 信号量的计数为 \(1\),\(b\) 和 \(c\) 的计数为 \(0\)。
线程 \(A\) 在执行 first()
方法时,首先需要获取 \(a\) 信号量,获取成功后执行 first()
方法,然后释放 \(b\) 信号量,这样线程 \(B\) 就可以获取 \(b\) 信号量并执行 second()
方法。
线程 \(B\) 在执行 second()
方法时,首先需要获取 \(b\) 信号量,获取成功后执行 second()
方法,然后释放 \(c\) 信号量,这样线程 \(C\) 就可以获取 \(c\) 信号量并执行 third()
方法。
线程 \(C\) 在执行 third()
方法时,首先需要获取 \(c\) 信号量,获取成功后执行 third()
方法,然后释放 \(a\) 信号量,这样线程 \(A\) 就可以获取 \(a\) 信号量并执行 first()
方法。
时间复杂度 \(O(1)\),空间复杂度 \(O(1)\)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
方法二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|