package org.test.pingpong;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String... args) throws InterruptedException {
// Choose one:
// countDownLatchSolution();
// cyclicBarrierSolution();
// queueMessagePassingSolution();
}
static volatile CountDownLatch pingLatch = new CountDownLatch(1);
static volatile CountDownLatch pongLatch = new CountDownLatch(1);
static class PingPongActivityZ extends Thread {
private final IAction action;
private final boolean isPing;
public PingPongActivityZ(IAction act) {
action = act;
isPing = act instanceof Ping;
}
@Override
public void run() {
while (true) {
try {
(isPing ? pingLatch : pongLatch).await();
action.doAction();
resetLatch();
(isPing ? pongLatch : pingLatch).countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void resetLatch() {
if (isPing) {
pingLatch = new CountDownLatch(1);
} else {
pongLatch = new CountDownLatch(1);
}
}
}
static void countDownLatchSolution() throws InterruptedException {
Ping ping = new Ping();
Pong pong = new Pong();
Thread tPing = new PingPongActivityZ(ping);
Thread tPong = new PingPongActivityZ(pong);
tPing.start();
tPong.start();
// progress processing
pingLatch.countDown();
tPing.join();
tPong.join();
}
static class PingPongActivity extends Thread {
private final IAction action;
private final CyclicBarrier actBarrier;
private final CyclicBarrier oppActBarrier;
public PingPongActivity(IAction act, CyclicBarrier actBarrier, CyclicBarrier oppActBarrier) {
action = act;
this.actBarrier = actBarrier;
this.oppActBarrier = oppActBarrier;
}
@Override
public void run() {
while (true) {
try {
actBarrier.await();
action.doAction();
oppActBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
static void cyclicBarrierSolution() throws InterruptedException {
Ping ping = new Ping();
Pong pong = new Pong();
CyclicBarrier pingBarrier = new CyclicBarrier(2);
CyclicBarrier pongBarrier = new CyclicBarrier(2);
Thread tPing = new PingPongActivity(ping, pingBarrier, pongBarrier);
Thread tPong = new PingPongActivity(pong, pongBarrier, pingBarrier);
tPing.start();
tPong.start();
// progress processing
try {
pingBarrier.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
tPing.join();
tPong.join();
}
static class PingPongActivityM implements Runnable {
private final IAction action;
private final ExecutorService oppActionActivity;
private final IAction oppositeAction;
private final ExecutorService actionActivity;
public PingPongActivityM(IAction act, ExecutorService actActivity, IAction oppAction, ExecutorService oppActActivity) {
action = act;
actionActivity = actActivity;
oppositeAction = oppAction;
oppActionActivity = oppActActivity;
}
@Override
public void run() {
action.doAction();
oppActionActivity.execute(new PingPongActivityM(oppositeAction, oppActionActivity, action, actionActivity));
}
}
static void queueMessagePassingSolution() {
ExecutorService pingActivity = Executors.newFixedThreadPool(1);
ExecutorService pongActivity = Executors.newFixedThreadPool(1);
Ping ping = new Ping();
Pong pong = new Pong();
pingActivity.execute(new PingPongActivityM(ping, pingActivity, pong, pongActivity));
}
}