[Java]LeetCode1116. 打印零与奇偶数 | Print Zero Even Odd
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
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"
假设有这么一个类:
class ZeroEvenOdd {
public ZeroEvenOdd(int n) { ... } // 构造函数
public void zero(printNumber) { ... } // 仅打印出 0
public void even(printNumber) { ... } // 仅打印出 偶数
public void odd(printNumber) { ... } // 仅打印出 奇数
}
相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程:
线程 A 将调用 zero(),它只输出 0 。
线程 B 将调用 even(),它只输出偶数。
线程 C 将调用 odd(),它只输出奇数。
每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n。
示例 1:
输入:n = 2
输出:"0102"
说明:三条线程异步执行,其中一个调用 zero(),另一个线程调用 even(),最后一个线程调用odd()。正确的输出为 "0102"。
示例 2:
输入:n = 5
输出:"0102030405"
4ms
1 import java.util.concurrent.*; 2 3 class ZeroEvenOdd { 4 private int n; 5 Semaphore s1, s2, s3; 6 7 public ZeroEvenOdd(int n) { 8 this.n = n; 9 s1 = new Semaphore(1); 10 s2 = new Semaphore(0); 11 s3 = new Semaphore(0); 12 } 13 14 // printNumber.accept(x) outputs "x", where x is an integer. 15 public void zero(IntConsumer printNumber) throws InterruptedException { 16 for (int i = 0; i < n; i++) { 17 s1.acquire(); 18 printNumber.accept(0); 19 if (i % 2 == 0) { 20 s3.release(); 21 } else { 22 s2.release(); 23 } 24 } 25 } 26 27 public void even(IntConsumer printNumber) throws InterruptedException { 28 for (int i = 2; i <= n; i += 2) { 29 s2.acquire(); 30 printNumber.accept(i); 31 s1.release(); 32 } 33 } 34 35 public void odd(IntConsumer printNumber) throws InterruptedException { 36 for (int i = 1; i <= n; i += 2) { 37 s3.acquire(); 38 printNumber.accept(i); 39 s1.release(); 40 } 41 } 42 }
7ms
1 import java.util.concurrent.locks.ReentrantLock; 2 import java.util.concurrent.locks.Condition; 3 import java.util.function.IntConsumer; 4 class ZeroEvenOdd { 5 private int n; 6 private ReentrantLock lock = new ReentrantLock(); 7 private Condition z = lock.newCondition(); 8 private Condition e = lock.newCondition(); 9 private Condition o = lock.newCondition(); 10 private boolean isZero = true; 11 private boolean isOld = true; 12 public ZeroEvenOdd(int n) { 13 this.n = n; 14 } 15 16 // printNumber.accept(x) outputs "x", where x is an integer. 17 public void zero(IntConsumer printNumber) throws InterruptedException { 18 lock.lock(); 19 for (int i = 1; i <= n; i++) { 20 if (!isZero) { 21 z.await(); 22 } 23 printNumber.accept(0); 24 isZero = false; 25 if (i%2!=0) { 26 o.signal(); 27 } else { 28 e.signal(); 29 } 30 } 31 lock.unlock(); 32 } 33 34 public void even(IntConsumer printNumber) throws InterruptedException { 35 lock.lock(); 36 for (int i = 2; i <= n; i+=2) { 37 if (isZero||isOld) { 38 e.await(); 39 } 40 printNumber.accept(i); 41 isZero = true; 42 isOld = true; 43 z.signal(); 44 } 45 lock.unlock(); 46 } 47 48 public void odd(IntConsumer printNumber) throws InterruptedException { 49 lock.lock(); 50 for (int i = 1; i <= n; i+=2) { 51 if (isZero||!isOld) { 52 o.await(); 53 } 54 printNumber.accept(i); 55 isZero = true; 56 isOld=false; 57 z.signal(); 58 } 59 lock.unlock(); 60 } 61 }
8ms
1 import java.util.concurrent.locks.*; 2 class ZeroEvenOdd { 3 private int n; 4 private volatile boolean e = false; 5 private volatile boolean o = false; 6 private ReentrantLock lock = new ReentrantLock(); 7 private Condition zeroCondition = lock.newCondition(); 8 private Condition evenCondition = lock.newCondition(); 9 private Condition oddCondition = lock.newCondition(); 10 11 12 public ZeroEvenOdd(int n) { 13 this.n = n; 14 } 15 16 // printNumber.accept(x) outputs "x", where x is an integer. 17 public void zero(IntConsumer printNumber) throws InterruptedException { 18 for (int i = 1; i <= n; i++) { 19 lock.lock(); 20 try { 21 if (i != 1) { 22 zeroCondition.await(); 23 } 24 printNumber.accept(0); 25 if (isOdd(i)) { 26 o = true; 27 oddCondition.signal(); 28 } else { 29 e = true; 30 evenCondition.signal(); 31 } 32 } finally { 33 lock.unlock(); 34 } 35 } 36 } 37 38 public void even(IntConsumer printNumber) throws InterruptedException { 39 for (int i = 2; i <= n; i += 2) { 40 lock.lock(); 41 try { 42 while (!e) { 43 evenCondition.await(); 44 } 45 e = false; 46 printNumber.accept(i); 47 zeroCondition.signal(); 48 } finally { 49 lock.unlock(); 50 } 51 } 52 53 } 54 55 public void odd(IntConsumer printNumber) throws InterruptedException { 56 for (int i = 1; i <= n; i += 2) { 57 lock.lock(); 58 try { 59 while (!o) { 60 oddCondition.await(); 61 } 62 o = false; 63 printNumber.accept(i); 64 zeroCondition.signal(); 65 } finally { 66 lock.unlock(); 67 } 68 } 69 } 70 71 private static boolean isOdd(final int number) { 72 return (number & 1) == 1; 73 } 74 }