題目
現在有兩種線程,氫 oxygen 和氧 hydrogen,你的目標是組織這兩種線程來產生水分子。
存在一個屏障(barrier)使得每個線程必須等候直到一個完整水分子能夠被產生出來。
氫和氧線程會被分別給予 releaseHydrogen 和 releaseOxygen 方法來允許它們突破屏障。
這些線程應該三三成組突破屏障并能立即組合產生一個水分子。
你必須保證產生一個水分子所需線程的結合必須發生在下一個水分子產生之前。
換句話說:
如果一個氧線程到達屏障時沒有氫線程到達,它必須等候直到兩個氫線程到達。
如果一個氫線程到達屏障時沒有其它線程到達,它必須等候直到一個氧線程和另一個氫線程到達。
書寫滿足這些限制條件的氫、氧線程同步代碼。
示例
輸入: "OOHHHH"
輸出: "HHOHHO"
解釋: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
條件:
- 輸入字符串的總長將會是 3n, 1 ≤ n ≤ 50;
- 輸入字符串中的 “H” 總數將會是 2n;
- 輸入字符串中的 “O” 總數將會是 n。
解答
private static Semaphore hydrogenSemaphore = new Semaphore(2);
private static Semaphore oxygenSemaphore = new Semaphore(0);
public static void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
hydrogenSemaphore.acquire();
// releaseHydrogen.run() outputs "H". Do not change or remove this line.
releaseHydrogen.run();
oxygenSemaphore.release();
}
public static void oxygen(Runnable releaseOxygen) throws InterruptedException {
oxygenSemaphore.acquire(2);
// releaseOxygen.run() outputs "O". Do not change or remove this line.
releaseOxygen.run();
hydrogenSemaphore.release(2);
}
測試方法:
public static void main(String[] args) {
for (int i = 0; i < 4; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
oxygen(new Runnable() {
@Override
public void run() {
System.out.print("O");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
for (int i = 0; i < 8; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
hydrogen(new Runnable() {
@Override
public void run() {
System.out.print("H");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
分析
1、使用J.U.C 的Semaphore,來讓線程獲取許可。
2、讓其中一個線程先執行,比如讓H先執行,創建一個H的信號量,初始值2
3、只有H執行2次后,會release O2次
4、這時O acquire(2) 執行一次O,release H 2次