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)); } }