我在一项作业中被要求实现 10 次正确调用“ping”和“pong”(意思是在 ping 之前没有 pong)的乒乓球游戏。也就是说,控制台的最终输出应该是:“ping!(1)”、“pong!(1)”、“ping!(2)”、“pong!(2)”等。
需求是用semaphores、reetrantlock和countdown latch实现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!");
}
}
提前致谢
最佳答案
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()
。
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 permit 开始,而 pong 应该从 0 开始。
ping
首先调用pingSemaphore
上的acquire()
并给出它。ping
打印出 ping。ping
在pongSemaphore
上调用release()
。- 这会唤醒
pong
(当然假设您的信号量代码有效)。 pong
打印pong
。pong
在pingSemaphore
上调用release()
。- 重复...
关于java - 正确实现乒乓球游戏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22997434/