4

課題で、「ping」と「pong」を正しく (ping の前に pong がないことを意味する) 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!");
    }
}

前もって感謝します

4

2 に答える 2

8

私の問題は、印刷順序が必ずしも要求どおりではないことです。何が間違っているのだろうかと思います。

問題は、ping スレッドと pong スレッドの両方が独自のセマフォを取得して解放していることだと思います。両方のセマフォを両方のスレッドに渡す必要があると思います。各スレッドはacquire()およびacquireSemaphorerelease()呼び出します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);

pingSemaphore1 許可で開始し​​、pong は 0 で開始する必要があります。

  1. ping最初に を呼び出すacquire()pingSemaphore、それが与えられます。
  2. pingping を出力します。
  3. pingで呼び出しrelease()ますpongSemaphore
  4. これで起動pongします (もちろん、セマフォ コードが機能すると仮定します)。
  5. pong印刷しpongます。
  6. pongで呼び出しrelease()ますpingSemaphore
  7. 繰り返す...
于 2014-04-10T20:06:33.773 に答える