Suppose you are given the following code:
class ZeroEvenOdd {
public ZeroEvenOdd(int n) { ... } // constructor
public void zero(printNumber) { ... } // only output 0's
public void even(printNumber) { ... } // only output even numbers
public void odd(printNumber) { ... } // only output odd numbers
}The same instance of ZeroEvenOdd will be passed to three different threads:
- Thread A will call zero() which should only output 0's.
- Thread B will call even() which should only ouput even numbers.
- Thread C will call odd() which should only output odd numbers.
Each of the thread is given a printNumber method to output an integer. Modify the given program to output the series 010203040506... where the length of the series must be 2n.
Example 1:
Input: n = 2
Output: "0102"
Explanation: There are three threads being fired asynchronously. One of them calls zero(), the other calls even(), and the last one calls odd(). "0102" is the correct output.Example 2:
Input: n = 5
Output: "0102030405"
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/print-zero-even-odd 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
多线程顺序打印0-1-0-2。
可以使用信号通知。
zero运行时:
打印even: zero 通知even
打印odd: zero通知odd
odd或even运行时:
全部都需要通知zero
import java.util.concurrent.Semaphore;
class ZeroEvenOdd {
private int n;
Semaphore zero,o,e;
public ZeroEvenOdd(int n) {
this.n = n;
zero = new Semaphore(1);
o = new Semaphore(0);
e = new Semaphore(0);
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void zero(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
zero.acquire();
printNumber.accept(0);
if ((i & 1) == 1) {
o.release();
} else {
e.release();
}
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
for (int i = 2; i <= n; i += 2) {
e.acquire();
printNumber.accept(i);
zero.release();
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i += 2) {
o.acquire();
printNumber.accept(i);
zero.release();
}
}
}还可以使用wati/notifyAll()来发送信号
设置zero和eo两个变量
zero = true代表通知zero等待
eo 表示开始打印奇偶数。e为偶数,o表示奇数
class ZeroEvenOdd {
private int n;
private boolean zero;// 打印0
private boolean eo;// 打印偶数或者奇数
public ZeroEvenOdd(int n) {
this.n = n;
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void zero(IntConsumer printNumber) throws InterruptedException {
synchronized(this){
for(int i = 0;i < n;i++){
while(zero){
this.wait();
}
printNumber.accept(0);
zero = true;
this.notifyAll();
}
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
for(int i = 1;i <= n;i += 2){
synchronized(this){
// zero运行完毕,eo=false 表示开始打印奇数
while(!(zero==true&&eo==false)){
this.wait();
}
printNumber.accept(i);
// 通知zero开始运行
zero = false;
// 通知偶数可以打印
eo = true;
this.notifyAll();
}
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
for(int i = 2;i <= n;i += 2){
synchronized(this){
// zero运行完毕,eo=true,开始打印偶数
while(!(zero==true&&eo==true)){
this.wait();
}
printNumber.accept(i);
// 通知zero开始运行
zero = false;
// 通知奇数可以打印
eo = false;
this.notifyAll();
}
}
}
}