1117. H2O 生成
现在有两种线程,氧 oxygen 和氢 hydrogen,你的目标是组织这两种线程来产生水分子。
存在一个屏障(barrier)使得每个线程必须等候直到一个完整水分子能够被产生出来。
氢和氧线程会被分别给予 releaseHydrogen 和 releaseOxygen 方法来允许它们突破屏障。
这些线程应该三三成组突破屏障并能立即组合产生一个水分子。
你必须保证产生一个水分子所需线程的结合必须发生在下一个水分子产生之前。
换句话说:
如果一个氧线程到达屏障时没有氢线程到达,它必须等候直到两个氢线程到达。
如果一个氢线程到达屏障时没有其它线程到达,它必须等候直到一个氧线程和另一个氢线程到达。
书写满足这些限制条件的氢、氧线程同步代码。
示例 1:
输入: “HOH”
输出: “HHO”
解释: “HOH” 和 “OHH” 依然都是有效解。
示例 2:
输入: “OOHHHH”
输出: “HHOHHO”
解释: “HOHHHO”, “OHHHHO”, “HHOHOH”, “HOHHOH”, “OHHHOH”, “HHOOHH”, “HOHOHH” 和 “OH
HOHH” 依然都是有效解。
提示:
输入字符串的总长将会是 3n, 1 ≤ n ≤ 50;
输入字符串中的 “H” 总数将会是 2n 。
输入字符串中的 “O” 总数将会是 n 。
Related Topics 多线程
👍 97 👎 0
/**
* 思路:
* 1、保证H、O是按比例配对出现的,可以采用两个信号量实现。另外还要保证3个一组,CyclicBarrier可以考虑
*/
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Semaphore;
class H2O {
private Semaphore hydrogenSemapore = new Semaphore(2);
private Semaphore oxygenSemapore = new Semaphore(1);
private CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {
//每轮结束释放信号量
hydrogenSemapore.release(2);
oxygenSemapore.release(1);
});
public H2O() {
}
public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
//用信号量2保证一轮过去两个氢
hydrogenSemapore.acquire();
//releaseHydrogen.run() outputs "H". Do not change or remove this line.
releaseHydrogen.run();
//用cyclicBarrier保证3个一轮
try {
cyclicBarrier.await();
} catch (Exception e) {
//no do
}
}
public void oxygen(Runnable releaseOxygen) throws InterruptedException {
//用信号量1保证一轮过去两个氧
oxygenSemapore.acquire();
//releaseOxygen.run() outputs "O". Do not change or remove this line.
releaseOxygen.run();
try {
//用cyclicBarrier保证3个一轮
cyclicBarrier.await();
} catch (Exception e) {
//no do
}
}
}
1116. 打印零与奇偶数
假设有这么一个类:
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”
Related Topics 多线程
👍 116 👎 0
/**
* 思路1:通过信号量思路几乎可以解决所有问题
* 思路2:通过ReentrantLock的Condition来解决
*/
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.IntConsumer;
class ZeroEvenOdd {
private Semaphore zeroSemaphore = new Semaphore(1);
private Semaphore evenSemaphore = new Semaphore(0);
private Semaphore oddSemaphore = new Semaphore(0);
private int n;
public ZeroEvenOdd(int n) {
this.n = n;
}
//printNumber.accept(x) outputs "x", where x is an integer.
public void zero(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
zeroSemaphore.acquire();
printNumber.accept(0);
if ((i & 1) == 0) {
evenSemaphore.release(1);
} else {
oddSemaphore.release(1);
}
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
if ((i & 1) == 0) {
evenSemaphore.acquire();
printNumber.accept(i);
zeroSemaphore.release(1);
}
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
if ((i & 1) == 1) {
oddSemaphore.acquire();
printNumber.accept(i);
zeroSemaphore.release(1);
}
}
}
}