正确实现乒乓游戏

Dan*_*elY 4 java concurrency semaphore countdownlatch reentrantlock

我被要求执行一个名为"ping"和"pong"的pingpong游戏(意思是ping之前没有乒乓)10次.意思是,控制台中的最终输出应该是:"ping!(1)","pong!(1)","ping!(2)","pong!(2)"等.

需求是使用信号量,reetrantlock和倒计时锁存器实现gamepingpongthread.

我的问题是打印顺序并不总是如我所要求的那样,我想知道我做错了什么.

这是代码:

// 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!");
    }
}
Run Code Online (Sandbox Code Playgroud)

提前致谢

Gra*_*ray 8

我的问题是打印顺序并不总是如我所要求的那样,我想知道我做错了什么.

我认为你的问题是ping和pong线程都在获取并释放自己的信号量.我认为你需要将两个信号量都传递给两个线程.每个线程调用acquire()on acquireSemaphorerelease()on releaseSemaphore.

  acquireSemaphore.acquire();
  System.out.println(message + "(" + i + ")");
  releaseSemaphore.release();
Run Code Online (Sandbox Code Playgroud)

线程看起来像:

public PlayPingPongThread (String msg, SimpleSemaphore acquireSemaphore,
        SimpleSemaphore releaseSemaphore)
Run Code Online (Sandbox Code Playgroud)

然后将线程初始化为:

// 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);
Run Code Online (Sandbox Code Playgroud)

pingSemaphore应与1个许可证和乒乓应该从0开始启动.

  1. ping首先调用acquire()pingSemaphore,它被赋予.
  2. ping 打印出ping.
  3. ping调用release()pongSemaphore.
  4. 这会唤醒pong(假设您的信号量代码当然有效).
  5. pong打印pong.
  6. pong调用release()pingSemaphore.
  7. 重复...