★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html
Suppose you are given the following code:java
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:git
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.github
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"async
假設有這麼一個類:函數
class ZeroEvenOdd {
public ZeroEvenOdd(int n) { ... } // 構造函數
public void zero(printNumber) { ... } // 僅打印出 0
public void even(printNumber) { ... } // 僅打印出 偶數
public void odd(printNumber) { ... } // 僅打印出 奇數
}
相同的一個 ZeroEvenOdd 類實例將會傳遞給三個不一樣的線程:ui
線程 A 將調用 zero(),它只輸出 0 。
線程 B 將調用 even(),它只輸出偶數。
線程 C 將調用 odd(),它只輸出奇數。
每一個線程都有一個 printNumber 方法來輸出一個整數。請修改給出的代碼以輸出整數序列 010203040506... ,其中序列的長度必須爲 2n。this
示例 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 }