2014-04-10 235 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