需求
leetcode 1116. 打印零与奇偶数 奇偶交替打印
给出一个正整数n,打印出0102.....0n的序列
3个线程共享对象 ZeroEvenOdd,t1 调用其zero();t2 调用odd();t3 调用even()方法
解题思路
Wait-notify模型进行三个线程的同步,两个变量,一个是序列当前数字(包含0),还有一个是递增数字
3个线程都有着个字的打印条件,如果不符合则wait,如果符合则打印,并唤醒其它两个线程。
代码实现
class ZeroEvenOdd {
private int n;
volatile private int cur = -1;
volatile private int num = 0;
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) {
while ( num < n) {
if (cur==0) {
wait();
} else {
cur = 0;
printNumber.accept(cur);
notifyAll();
}
}
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
synchronized (this) {
while (num < n) {
if (cur!=0 || (num&1) ==0 ) { //不满足条件 条件是 序列当前为0,且上一个有效数字是奇数
wait();
} else {
cur = ++num; //获取下一个偶数
printNumber.accept(cur);
notifyAll();
}
}
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
synchronized (this) {
while (num < n) {
if (cur!=0 || (num&1) ==1 ) { //不满足条件 条件是 序列当前为0,且上一个有效数字是奇数
wait();
} else {
cur = ++num; //获取下一个奇数
printNumber.accept(cur);
notifyAll();
}
}
}
}
}
测试验证
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
ZeroEvenOdd zeroEvenOdd = new ZeroEvenOdd(5);
pool.execute(new Runnable() {
@Override
public void run() {
try {
zeroEvenOdd.zero(new print());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
pool.execute(new Runnable() {
@Override
public void run() {
try {
zeroEvenOdd.even(new print());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
pool.execute(new Runnable() {
@Override
public void run() {
try {
zeroEvenOdd.odd(new print());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
static class print implements IntConsumer {
@Override
public void accept(int value) {
System.out.print(value);
}
}