java - 为什么线程通信在java中不起作用?
问题描述
我正在开发一个基于 Java 的小型游戏,我正在尝试由玩家 1 发射导弹,直到玩家 1 没有错过目标,一旦玩家 1 错过目标,那么火燕将移动到玩家 2,玩家 2 将开始射击,直到他错过目标,反之亦然。
这里 Player-1 和 Player-2 都是 JavaRunnable
任务,请找到以下代码:
public class GameRender implements IGame {
private Game game;
private Player player1, player2;
private Lock lock = new ReentrantLock();
Condition notPlayer1TernCondition = lock.newCondition();
Condition notPlayer2TernCondition = lock.newCondition();
public GameRender(Game game, Player player1, Player player2) {
this.game = game;
this.player1 = player1;
this.player2 = player2;
}
@Override
public void create() {
}
@Override
public void render() {
//ExecutorService executorService = Executors.newFixedThreadPool(2);
Player1Task plater1 = new Player1Task(player1.getTargetLocations(), true);
Player2Task plater2 = new Player2Task(player2.getTargetLocations(), false);
Thread t1 = new Thread(plater1);
Thread t2 = new Thread(plater2);
t1.start();
t2.start();
}
@Override
public void over() {
}
class Player1Task implements Runnable {
private List<TargetLocation> playerOnesTargetLocationList;
private boolean isHitTarget = false;
private int fireCount = 0;
private boolean yourTern;
Player1Task(List<TargetLocation> playerOnesTargetLocationList, boolean yourTern) {
this.playerOnesTargetLocationList = playerOnesTargetLocationList;
this.yourTern = yourTern;
}
@Override
public void run() {
try {
lock.lock();
fire();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
private void fire() throws InterruptedException {
while (fireCount != playerOnesTargetLocationList.size()) {
if (!yourTern) {
notPlayer1TernCondition.await();
}
TargetLocation location = playerOnesTargetLocationList.get(fireCount);
if (player2.getOwnField().hasShip(location.getxPos(), location.getyPos())) {
} else {
System.out.println("Player-1 else");
yourTern = false;
notPlayer2TernCondition.signalAll();
}
fireCount++;
}
}
}
class Player2Task implements Runnable {
private List<TargetLocation> playerTwosTargetLocationList;
private boolean isHitTarget = false;
private int fireCount = 0;
private boolean yourTern;
Player2Task(List<TargetLocation> playerTwosTargetLocationList, boolean youTern) {
this.playerTwosTargetLocationList = playerTwosTargetLocationList;
this.yourTern = youTern;
}
@Override
public void run() {
lock.lock();
try {
fire();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
private void fire() throws InterruptedException {
while (fireCount != playerTwosTargetLocationList.size()) {
if (!yourTern) {
notPlayer2TernCondition.await();
}
TargetLocation location = playerTwosTargetLocationList.get(fireCount);
if (player1.getOwnField().hasShip(location.getxPos(), location.getyPos())) {
} else {
System.out.println("p2 else");
yourTern = false;
notPlayer1TernCondition.signalAll();
}
fireCount++;
}
}
}
}
上面的代码没有按预期工作,第一次执行 Player-1,之后代码卡住了。
任何解释都非常感谢。
解决方案
您永远不会将 yourTern 设置为 true。(可以使用一个共享变量来表示哪个玩家有回合)
解释:假设最初 Player1 有锁并且当 Player1 的 yourTern 为真时触发。假设它未命中,那么您将向 Player2(尚未等待)发出信号并将 yourTern 设置为 false 并释放锁(通过notPlayer1TernCondition.await()
在下一次迭代中调用方法)。
这个锁将被 Player2 获取,它会调用它,notPlayer2TernCondition.await()
因为它的 yourTern 为 false。
两个线程现在都将永远进入等待状态。
推荐阅读
- php - Symfony YAML:格式化输出
- html - HTML页面刷新
- gradle - 将 sourceCompatibility 和 targetCompatibility 从 1.8 更改为 13 时,任务“:test”的 Gradle 执行失败
- rest - JSON错误 | 无数据,空输入 1:1
- c# - Unity 中的 UnityScript 到 C#
- ubuntu - OpenSSL KEYUPDATE 和“SSL_key_update:错误的 ssl 版本”
- ag-grid - 有没有办法在 ag-grid 中将 detailRowHeight 道具设置为 100%?
- sql - 根据时差和出现次数选择重复行
- c++ - 如何在 C++ 中使用 [] 运算符获取对象
- 3des - 我可以在 google KMS HSM 中使用 3DES 密钥吗?