2014-04-10 279 views
4

我被要求在一項任務中實施10次正確稱爲「ping」和「pong」的pingpong遊戲(意思是,在ping之前沒有pong)。這意味着,控制檯中的最終輸出應該是:「ping!(1)」,「pong!(1)」,「ping!(2)」,「pong!(2)」等。正確實施pingpong遊戲

需求是用信號量,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!"); 
    } 
} 

在此先感謝

+0

我該怎麼做,以確保那麼,我用我的工具呢? – DanielY

+0

每個線程有2個信號量,ping和pong?我會如何讓他們等待? – DanielY

+0

這是錯誤的。我已經將我的意見轉移到了答案上。 – Gray

回答

8

我的問題是打印順序並不總是要求的,我不知道我做錯了。

我認爲你的問題是ping和pong線程都在獲取和釋放他們自己的信號量。我認爲你需要通過兩個信號量兩個線程。每個線程在releaseSemaphore上的acquireSemaphorerelease()上調用acquire()

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

線程看起來像:

// 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開始:

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

然後線程的初始化。

  1. pingpingSemaphore上首先撥打acquire()並給出。
  2. ping打印出ping。
  3. ping來電release()pongSemaphore
  4. 這醒來pong(假設你的信號量代碼當然可用)。
  5. pong打印pong
  6. pongpingSemaphore調用release()
  7. 重複...
+0

現在好多了!!! :) 非常感謝您的幫助 – DanielY