正确实施乒乓游戏 [英] Implementing pingpong game correctly

查看:69
本文介绍了正确实施乒乓游戏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一项作业中被要求实施10次正确的乒乓球游戏,该游戏正确地调用了"ping"和"pong"(意思是在ping之前没有pong).意思是,控制台中的最终输出应该是:"ping!(1)","pong!(1)","ping!(2)","pong!(2)"等.

I'm requested in an assignment to implement pingpong game that called "ping" and "pong" correctly (meaning, no pong before ping) 10 times. Meaning, the final output in the console should be: "ping!(1)", "pong!(1)", "ping!(2)", "pong!(2)" etc.

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

The demand is to implement gamepingpongthread with semaphores, reetrantlock and countdown latch.

我的问题是打印顺序并非总是按要求进行,我想知道我做错了什么.

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

代码如下:

// 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!");
    }
}

预先感谢

推荐答案

我的问题是打印顺序并非总是按要求进行,我想知道我做错了什么.

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

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

I think your problem is that both the ping and pong threads are acquiring and releasing their own semaphore. I think you need to pass both semaphores to both threads. Each thread calls acquire() on the acquireSemaphore and release() on the 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个许可开始,而pong一个应该以0开始.

The pingSemaphore should start with 1 permit and the pong one should start with 0.

  1. ping 首先在 pingSemaphore 上调用 acquire()并给出
  2. .
  3. ping 打印出ping.
  4. ping 调用 pongSemaphore 上的 release().
  5. 这会唤醒 pong (当然,假设您的信号灯代码有效).
  6. pong 打印 pong .
  7. pong pingSemaphore 上调用 release().
  8. 重复...
  1. ping first calls acquire() on the pingSemaphore and it is given.
  2. ping prints out ping.
  3. ping calls release() on the pongSemaphore.
  4. This wakes up pong (assuming your semaphore code works of course).
  5. pong prints pong.
  6. pong calls release() on the pingSemaphore.
  7. repeat...

这篇关于正确实施乒乓游戏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆