題目描述
現有函數 printNumber 可以用一個整數參數調用,并輸出該整數到控制臺。
例如,調用 printNumber(7) 將會輸出 7 到控制臺。
給你類 ZeroEvenOdd 的一個實例,該類中有三個函數:zero、even 和 odd 。ZeroEvenOdd 的相同實例將會傳遞給三個不同線程:
線程 A:調用 zero() ,只輸出 0
線程 B:調用 even() ,只輸出偶數
線程 C:調用 odd() ,只輸出奇數
修改給出的類,以輸出序列 “010203040506…” ,其中序列的長度必須為 2n 。
實現 ZeroEvenOdd 類:
ZeroEvenOdd(int n) 用數字 n 初始化對象,表示需要輸出的數。
void zero(printNumber) 調用 printNumber 以輸出一個 0 。
void even(printNumber) 調用printNumber 以輸出偶數。
void odd(printNumber) 調用 printNumber 以輸出奇數。
示例 1:
輸入:n = 2
輸出:“0102”
解釋:三條線程異步執行,其中一個調用 zero(),另一個線程調用 even(),最后一個線程調用odd()。正確的輸出為 “0102”。
示例 2:
輸入:n = 5
輸出:“0102030405”
提示:
1 <= n <= 1000
解題思路
此題與1115很像,都是線程的交替執行問題,不同的是有三個線程,可以用同步信號量來實現交替打印。
值得注意的是,像1115題中那樣通過while循環等待同步信號量的方式在此題會超時,所以我們在等待的時候需要釋放cpu資源, 可以使用Thread.yield() 實現
代碼實現
import java.util.function.IntConsumer;class ZeroEvenOdd {private int n;volatile int flag = 2;public ZeroEvenOdd(int n) {this.n = n;}// printNumber.accept(x) outputs "x", where x is an integer.public void zero(IntConsumer printNumber) throws InterruptedException {for(int i = 1; i <= n; i++) {while(flag != 2) {Thread.yield();}printNumber.accept(0);flag = i % 2;}}public void even(IntConsumer printNumber) throws InterruptedException {for(int i = 2; i <= n; i += 2) {while(flag != 0) {Thread.yield();}printNumber.accept(i);flag = 2;}}public void odd(IntConsumer printNumber) throws InterruptedException {for(int i = 1; i <= n; i += 2) {while(flag != 1) {Thread.yield();}printNumber.accept(i);flag = 2;}}
}