62,614
社区成员
发帖
与我相关
我的任务
分享
public class Solution1116 {
static CountDownLatch cdl = new CountDownLatch(3);
public static void main(String[] args) {
ZeroEvenOdd zeo = new ZeroEvenOdd(9);
// 重定向输出流相关操作
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
PrintStream old = System.out;
System.setOut(ps);
// 初始化线程和3个Runnable
IntConsumer ic = System.out::print;
ExecutorService es = Executors.newFixedThreadPool(3);
Runnable r0 = ConsumerCatch.runnableWrap(zeo::zero, ic); // 需要ConsumerCatch接口的支持
Runnable r1 = ConsumerCatch.runnableWrap(zeo::odd, ic);
Runnable r2 = ConsumerCatch.runnableWrap(zeo::even, ic);
while (true) {
es.submit(r0);
es.submit(r1);
es.submit(r2);
try {
cdl.await(); // 阻塞主线程
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印并比对结果
ps.flush();
System.setOut(old);
String s = baos.toString();
System.out.println(s);
if (!s.equals("010203040506070809")) {
break;
}
// 全体重置
baos.reset();
cdl = new CountDownLatch(3);
zeo.reset();
System.setOut(ps);
}
}
private static class ZeroEvenOdd {
private int n;
private volatile int current = 1; // 弃用
private AtomicInteger ai = new AtomicInteger(1);
private volatile Thread t0 = null;
private volatile Thread t1 = null;
private volatile Thread t2 = null;
public ZeroEvenOdd(int n) {
this.n = n;
}
// 测试用,用来使该对象恢复到初始状态
public void reset() {
ai.set(1);
t0 = null;
t1 = null;
t2 = null;
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void zero(IntConsumer printNumber) throws InterruptedException {
t0 = Thread.currentThread();
for (int i = 0; i < n; i++) {
printNumber.accept(0);
while (t1 == null || t2 == null) {} // 自旋保证初始化 + 内存屏障
if ((ai.get() & 1) == 1)
LockSupport.unpark(t1);
else
LockSupport.unpark(t2);
if (i != n - 1)
LockSupport.park();
}
Solution1116.cdl.countDown(); // 仅测试,用来给主线程放行
}
public void even(IntConsumer printNumber) throws InterruptedException {
t2 = Thread.currentThread();
for (int i = 0; i < n / 2; i++) {
LockSupport.park();
printNumber.accept(ai.getAndIncrement());
LockSupport.unpark(t0);
}
Solution1116.cdl.countDown(); // 仅测试,用来给主线程放行
}
public void odd(IntConsumer printNumber) throws InterruptedException {
t1 = Thread.currentThread();
for (int i = 0; i < n - n / 2; i++) {
LockSupport.park();
printNumber.accept(ai.getAndIncrement());
LockSupport.unpark(t0);
}
Solution1116.cdl.countDown(); // 仅测试,用来给主线程放行
}
}
}
@FunctionalInterface
public interface ConsumerCatch<T>{
static <T> Runnable runnableWrap(ConsumerCatch<T> ct, T t) {
return () -> {
try {
ct.accept(t);
} catch (Exception e) {
e.printStackTrace();
}
};
}
static <T> Thread threadWrap(ConsumerCatch<T> ct, T t) {
return new Thread(() -> {
try {
ct.accept(t);
} catch (Exception e) {
e.printStackTrace();
}
});
}
void accept(T t) throws Exception;
}
if (i != n - 1)
LockSupport.park();