gpt4 book ai didi

Java多线程: how to notify() a single thread after all threads are ready

转载 作者:行者123 更新时间:2023-12-01 18:32:37 24 4
gpt4 key购买 nike

我正在编写一个游戏,其中玩家可以是本地或远程的,因此我必须使用多线程读取他所做的“移动”。

我有一个 PlayerLoop 线程,它最初在多个 Player 线程上调用 start()。之后,PlayerLoop 应以循环方式重复唤醒单个 Player(从第一个到最后一个),直到游戏结束。

但是,Player 并不总是会醒来:有时 PlayerLoop 会通知正确的 Player,但它这样做得太早了(玩家尚未“等待轮到他”)。

具体来说,当我第一次启动 PlayerLoop 时,它似乎工作正常,但如果在游戏过程中我取消比赛并开始新的比赛,那么每个 Player code> 只是永远等待轮到他们。

这是PlayerLoop:

public class PlayerLoop extends Thread {
@Override
public void run() {
System.out.println("Thread [" + Thread.currentThread().getName()
+ "] is alive.");
this.startPlayers(); // cycles Players and calls .start()
while (true) {
Player current = this.getCurrentPlayer();

current.connect(); // connect to this Player
synchronized (current) {
try {
System.out.println("Notifying Thread [" + current.getName()
+ "] that it's his turn.");
current.notify(); // the player thread "resumes" to eventually produce a "move"
current.wait(); // wait for the "move" to be ready
} catch (InterruptedException e) {
// The game loop is interrupted, terminate thread
break;
}
}
this.applyMove(current.getMove()); // use the "move"
current.disconnect(); // disconnect this Player

this.goToNextPlayer();
}
System.out.println("Terminating players...");
this.stopPlayers(); // cycles Players and calls .interrupt()
System.out.println("Thread [" + Thread.currentThread().getName()
+ "] is dead.");
}

目前我没有测试“远程”部分,所以这里只是 LocalPlayer 类,它扩展了 Player,它扩展了 Thread >:

public class LocalPlayer extends Player {
@Override
public void run() {
System.out.println("Thread [" + Thread.currentThread().getName()
+ "] is alive.");
while (true) {
// Wait my turn
synchronized (this) {
try {
System.out.println("Thread ["
+ Thread.currentThread().getName()
+ "] is waiting its turn.");
this.wait();
} catch (InterruptedException e) {
// We are stopping all the players, so terminate thread
break;
}
System.out.println("Thread ["
+ Thread.currentThread().getName()
+ "] has come to its turn.");
}
// Wait for mainLoop to produce a Move
synchronized (__SomeGameLoop__) {
System.out.println("Thread ["
+ Thread.currentThread().getName()
+ "] is waiting a move.");
try {
__SomeGameLoop__.wait();
} catch (InterruptedException e) {
// PlayerLoop was interrupted, and he is now interrupting me, so terminate thread
break;
}
System.out.println("Thread ["
+ Thread.currentThread().getName()
+ "] has been notified of a move.");
}

// Get produced move
this.move = __SomeGameLoop__.getMove();

// Signal monitor
synchronized (this) {
// Notify that I have read the move and that I can communicate it
this.notify();
}
}
System.out.println("Thread [" + Thread.currentThread().getName()
+ "] is dead.");
}
}

上面的代码可能不精确且过于简单,但以下是游戏输出的摘录:

Creating threads...
Thread [PlayerLoop] is alive.
Thread [Player 1] is alive.
Thread [Player 2] is alive.
Thread [Player 2] is waiting its turn.
Thread [Player 1] is waiting its turn.
Notifying Thread [Player 1] that it's his turn.
Thread [Player 1] has come to its turn.
Thread [Player 1] is waiting a move.
GameLoop notifies that a move has been done.
Thread [Player 1] has been notified of a move.
Notify that I have read that move and I can communicate it
Thread [Player 1] is waiting its turn.
Notifying Thread [Player 2] that it's his turn.
Thread [Player 2] has come to its turn.
Thread [Player 2] is waiting a move.
GameLoop notifies that a move has been done.
Thread [Player 2] has been notified of a move.
Notify that I have read that move and I can communicate it
Thread [Player 2] is waiting its turn.
Notifying Thread [Player 1] that it's his turn.
Thread [Player 1] has come to its turn.
Thread [Player 1] is waiting a move.
GameLoop notifies that a move has been done.
Thread [Player 1] has been notified of a move.
Notify that I have read that move and I can communicate it
Thread [Player 1] is waiting its turn.
Notifying Thread [Player 2] that it's his turn.
Thread [Player 2] has come to its turn.
Thread [Player 2] is waiting a move.
Terminating players...
Thread [PlayerLoop] is dead.
PlayerLoop was interrupted, and he is now interrupting me, so terminate thread [Player 2]
We are stopping all the players, so terminate thread [Player 1]
Thread [Player 1] is dead.
Thread [Player 2] is dead.

Creating threads...
Thread [PlayerLoop] is alive.
Thread [Player 1] is alive.
Notifying Thread [Player 1] that it's his turn.
Thread [Player 1] is waiting its turn.
Thread [Player 2] is alive.
Thread [Player 2] is waiting its turn.
....(and here it hangs indefinitely)....

第二次创建线程时,PlayerLoop 过早通知Player。如何确保仅在所有 Playerwait() 后才 notify() 一个 Player在各自的显示器上?

最佳答案

玩家不应该等待轮到他们,除非还没有轮到他们。等待条件是无条件的。因此,如果您不需要等待某个条件,就不要等待。调用 wait 的方法之所以是同步的,是为了让您可以在等待之前绝对确定需要等待。

如果有什么事情需要等待,等待总是安全的。如果没有什么可等待的,那就没有理由等待。不要等待已经发生的事情,它不会发生。

关于Java多线程: how to notify() a single thread after all threads are ready,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23464950/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com