package edu.vuum.mocca; import java.util.concurrent.Semaphore; /** * This class implements a Java program that creates two threads, * "ping" and "pong", that use a pair of Java Semaphores to * alternately print "Ping" and "Pong", respectively, on the display. */ public class PlayPingPong implements Runnable { /** * Number of iterations to ping/pong. */ private final int mMaxIterations; /** * This class uses semaphores to implement the acquire() * and release() hook methods that schedule the ping/pong * algorithm. */ static class PingPongThread extends Thread { /** * Number of iterations to ping/pong. */ private final int mMaxIterations; /** * Data member that indicates the string to print (typically a * "ping" or a "pong"). */ private final String mStringToPrint; /** * Semaphores that schedule the ping/pong algorithm */ private final Semaphore mFirstSema; private final Semaphore mSecondSema; /** * Constructor initializes the various fields. */ public PingPongThread(int maxIterations, String stringToPrint, Semaphore firstSema, Semaphore secondSema) { mMaxIterations = maxIterations; mStringToPrint = stringToPrint; mFirstSema = firstSema; mSecondSema = secondSema; } /** * Hook method for ping/pong acquire. */ void acquire() { mFirstSema.acquireUninterruptibly(); } /** * Hook method for ping/pong release. */ void release() { mSecondSema.release(); } /** * This method runs in a separate thread of control and * implements the core ping/pong algorithm. */ public void run() { // Loop repeatedly performing the protocol for printing a // "ping" or a "pong" on the display. for (int loopsDone = 1; loopsDone <= mMaxIterations; ++loopsDone) { acquire(); System.out.println(mStringToPrint + "(" + loopsDone + ")"); release(); } // Exit the thread when the loop is done. } } /** * Constructor stores the PlatformStrategy and the number of * iterations to play ping/pong. */ public PlayPingPong (int maxIterations) { // Number of iterations to perform pings and pongs. mMaxIterations = maxIterations; } /** * Start running the ping/pong code, which can be called from a * main() function in a Java class, an Android Activity, etc. */ public void run() { // Let the user know we're starting. System.out.println("Ready...Set...Go!"); // Create the semaphores that schedule threads printing "ping" // and "pong" in the correct alternating order. final Semaphore pingSema = new Semaphore(1); // Starts out unlocked. final Semaphore pongSema = new Semaphore(0); // Create the ping and pong threads. final PingPongThread pingThread = new PingPongThread(mMaxIterations, "ping", pingSema, pongSema); final PingPongThread pongThread = new PingPongThread(mMaxIterations, "pong", pongSema, pingSema); // Start ping and pong threads, which calls their run() // methods. pingThread.start(); pongThread.start(); try { // Barrier synchronization to wait for all work to be done // before exiting play(). pingThread.join(); pongThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } // Let the user know we're done. System.out.println("Done!"); } }