The correct implementation of the ping pong game

I have been instructed to execute the pingpong game, which is called "ping" and "pong" correctly (meaning that there is no pong before ping) 10 times. The value of the final output in the console should be: "ping! (1)", "pong! (1)", "ping! (2)", "pong! (2)", etc.

The requirement is to implement gamepingpongthread using semaphores, blocking re-launch and countdown.

My problem is that the print order is not always requested, and I wonder what I'm doing wrong.

Here is the code:

// Import the necessary Java synchronization and scheduling classes.
import java.util.concurrent.Semaphore;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;

/**
 * @class PingPongRight
 *
 * @brief This class implements a Java program that creates two
 *        instances of the PlayPingPongThread and start these thread
 *        instances to correctly alternate printing "Ping" and "Pong",
 *        respectively, on the console display.
 */
public class PingPongRight
{
    /**
     * @class SimpleSemaphore
     *
     * @brief This class provides a simple counting semaphore
     *        implementation using Java a ReentrantLock and a
     *        ConditionObject.
     */
    static public class SimpleSemaphore
    {
        private int mPermits;
        private ReentrantLock lock = new ReentrantLock();
        private Condition isZero = lock.newCondition();

        /**
         * Constructor initialize the data members. 
         */
        public SimpleSemaphore (int maxPermits)
        { 
            mPermits = maxPermits;
        }

        /**
         * Acquire one permit from the semaphore.
         */
        public void acquire() throws InterruptedException
        {
            lock.lock();
            while (mPermits == 0)
                isZero.await();
            mPermits--;
            lock.unlock();
        }

        /**
         * Return one permit to the semaphore.
         */
        void release() throws InterruptedException
        {
            lock.lock();
            try {
                mPermits++;
                isZero.signal();
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * Number of iterations to run the test program.
     */
    public static int mMaxIterations = 10;

    /**
     * Latch that will be decremented each time a thread exits.
     */
    public static CountDownLatch latch = new CountDownLatch(2);

    /**
     * @class PlayPingPongThread
     *
     * @brief This class implements the ping/pong processing algorithm
     *         using the SimpleSemaphore to alternate printing "ping"
     *         and "pong" to the console display.
     */
    public static class PlayPingPongThread extends Thread
    {
        private String message;
        private SimpleSemaphore semaphore;

        /**
         * Constructor initializes the data member.
         */
        public PlayPingPongThread (String msg, SimpleSemaphore pingOrPong)
        {
            message = msg;
            semaphore = pingOrPong;
        }

        /**
         * Main event loop that runs in a separate thread of control
         * and performs the ping/pong algorithm using the
         * SimpleSemaphores.
         */
        public void run () 
        {
            for (int i = 1 ; i <= mMaxIterations ; i++) {
                try {
                    semaphore.acquire();
                    System.out.println(message + "(" + i + ")");
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            latch.countDown();
        }
    }

    /**
     * The main() entry point method into PingPongRight program. 
     */
    public static void main(String[] args) {
        try {         
            // Create the ping and pong SimpleSemaphores that control
            // alternation between threads.
            SimpleSemaphore pingSemaphore = new SimpleSemaphore(mMaxIterations);
            SimpleSemaphore pongSemaphore = new SimpleSemaphore(mMaxIterations);

            System.out.println("Ready...Set...Go!");

            // Create the ping and pong threads, passing in the string
            // to print and the appropriate SimpleSemaphores.
            PlayPingPongThread ping = new PlayPingPongThread("Ping!", pingSemaphore);
            PlayPingPongThread pong = new PlayPingPongThread("Pong!", pongSemaphore);

            // Initiate the ping and pong threads, which will call the run() hook method.
            ping.start();
            pong.start();

            // Use barrier synchronization to wait for both threads to finish.
            latch.await();
        } 
        catch (java.lang.InterruptedException e)
            {}

        System.out.println("Done!");
    }
}

Thanks in advance

+4
source share
1 answer

My problem is that the print order is not always requested, and I wonder what I'm doing wrong.

, , ping, pong . , . acquire() acquireSemaphore release() releaseSemaphore.

  acquireSemaphore.acquire();
  System.out.println(message + "(" + i + ")");
  releaseSemaphore.release();

:

public PlayPingPongThread (String msg, SimpleSemaphore acquireSemaphore,
        SimpleSemaphore releaseSemaphore)

:

// ping acquires on the ping, releases the pong
PlayPingPongThread ping = new PlayPingPongThread("Ping!", pingSemaphore, pongSemaphore);
// pong acquires on the pong, releases the ping
PlayPingPongThread pong = new PlayPingPongThread("Pong!", pongSemaphore, pingSemaphore);

pingSemaphore 1 , 0.

  • ping acquire() pingSemaphore, .
  • ping .
  • ping release() pongSemaphore.
  • pong (, , ).
  • pong pong.
  • pong release() pingSemaphore.
  • ...
+8

Source: https://habr.com/ru/post/1535991/


All Articles