Java 线程等待用户单击某个内容
我正在准备玩五子棋的申请 我已经创建了漂亮的GUI,现在我正在与核心引擎进行斗争 有一个类Java 线程等待用户单击某个内容,java,multithreading,swing,exception,mouselistener,Java,Multithreading,Swing,Exception,Mouselistener,我正在准备玩五子棋的申请 我已经创建了漂亮的GUI,现在我正在与核心引擎进行斗争 有一个类GameEngine,它有同步的方法来移动。 还有一些类实现了IClient接口,它们是“玩家”。 首先要做的是实现PlayerClient,它连接到BoardPanel,并在BoardPanel(代表gomoku板)中的MouseListener打开时移动。我希望我的应用程序是开放的,以实现也电脑播放器。这就是为什么它如此复杂 所以。。。问题: 我的GameEngine类如下所示: public clas
GameEngine
,它有同步的方法来移动。
还有一些类实现了IClient
接口,它们是“玩家”。
首先要做的是实现PlayerClient
,它连接到BoardPanel
,并在BoardPanel
(代表gomoku板)中的MouseListener
打开时移动。我希望我的应用程序是开放的,以实现也电脑播放器。这就是为什么它如此复杂
所以。。。问题:
我的GameEngine
类如下所示:
public class GameEngine {
private IClient blackPlayer;
private IClient whitePlayer;
private GameState gameState;
...
public void play() {
blackPlayer.run();
whitePlayer.run();
}
public synchronized void move(Move move) throws IllegalMoveException {
gameState.move(move);
if (move.isBlackMove()){
whitePlayer.notify();
}else{
blackPlayer.notify();
}
}
public synchronized void waitForYourTurn(boolean color){
try {
while (gameState.isBlackToMove()!=color) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private synchronized void movePicked() {
if (gameState.isBlackToMove() && blackClient != null) {
blackClient.notify();
clearCurrentMove();
}
if (!gameState.isBlackToMove() && whiteClient != null) {
whiteClient.notify();
clearCurrentMove();
}
}
我的客户端类有run()方法:
在我写“//waitForPickedMove()”的地方,客户端应该等待用户单击主板上的正确位置。所以我的董事会班上有一个鼠标听器:
private class MoveMouseListener implements MouseListener {
@Override
public synchronized void mouseReleased(MouseEvent e) {
if (gameState == null) {
return;
}
if (currentMove != null) {
movePicked();
repaint();
}
}
}
currentMove当然是用户通过点击线路板选择的移动。movePicked()的外观如下所示:
public class GameEngine {
private IClient blackPlayer;
private IClient whitePlayer;
private GameState gameState;
...
public void play() {
blackPlayer.run();
whitePlayer.run();
}
public synchronized void move(Move move) throws IllegalMoveException {
gameState.move(move);
if (move.isBlackMove()){
whitePlayer.notify();
}else{
blackPlayer.notify();
}
}
public synchronized void waitForYourTurn(boolean color){
try {
while (gameState.isBlackToMove()!=color) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private synchronized void movePicked() {
if (gameState.isBlackToMove() && blackClient != null) {
blackClient.notify();
clearCurrentMove();
}
if (!gameState.isBlackToMove() && whiteClient != null) {
whiteClient.notify();
clearCurrentMove();
}
}
我尝试在许多地方放置wait()
。我尝试反向控制并将其放入Board
类中,因此它调用了客户机类中的方法(setCurrentMove(Move-Move))。不幸的是,我无法达到我想要的。我总是得到IllegalMonitorStateException
或我的GUI块
我希望我能充分解释我的问题。我会感谢你的帮助
编辑:
我很确定我应该同步某个东西,但我真的不知道是什么
编辑2:
@Override
public void enemyMoved() {
myTurn = true;
executorService.move();
}
private class ExecutorService implements Runnable {
@Override
public void run() {
while (gameState.getWinner() == 0) {
System.out.println("Calculating: j= " + j);
if (j == 3)
j = 4;
else
j = 3;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void move() {
while (myTurn) {
try {
gameEngine.move(new Move(black, j, i++));
myTurn = false;
} catch (IllegalMoveException e) {
e.printStackTrace();
}
}
}
}
很难说它到底是什么:很多碎片。但看起来您应该按照以下说明同步通知呼叫:
()很难说清楚它到底是什么:很多碎片。但看起来您应该按照以下说明同步通知呼叫:
()嗨,我建议你睡觉()并通知()。如果您想在未知时间停止某个线程,请让它睡眠,当您再次需要它时,请让它通知()。嗨,我建议您睡眠()和通知()。如果您想在未知时间停止某个线程,请让它睡眠,当您再次需要它时,请让它通知()。游戏引擎无需一直占用线程,在无事可做时将其阻塞。您应该将其重新设计为反应式:代码在事件处理程序正在执行的线程中有事件时执行。这样您就不需要任何
等待
-通知
机制
如果您希望允许播放器实现在不占用调用线程的情况下从容进行,请在设计API时牢记异步性:
IClient
将有一个表示“其他播放器已移动”的方法,该方法不会立即返回播放器的移动。IClient
将在移动时调用游戏引擎上的一个方法。游戏引擎不需要不断占用线程,在无事可做时阻塞线程。您应该将其重新设计为反应式:代码在事件处理程序正在执行的线程中有事件时执行。这样您就不需要任何等待
-通知
机制
如果您希望允许播放器实现在不占用调用线程的情况下从容进行,请在设计API时牢记异步性:
IClient
将有一个表示“其他播放器已移动”的方法,该方法不会立即返回播放器的移动。IClient
将通过其移动调用游戏引擎上的一个方法。“这就是为什么它如此复杂的原因。”为了更快地获得更好的帮助,只需多线程和鼠标单击即可发布您的最佳尝试。Swing。嗯,这是一个很大的应用程序,现在有很多类。我试图删掉重要的东西。游戏引擎和客户端之间的多线程工作正常。我试着硬编码这个动作。当我尝试等待GUI时出现问题。我只是不确定应该等待什么以及应该在哪里得到通知。所以基本上我需要帮助来实现这个注释:Move waitForPickedMove()和通知somhow。。。与movePicked()中的不完全一样。“这就是为什么它如此复杂。”为了更快地获得更好的帮助,请发布一篇您的最佳尝试,只需使用多线程和鼠标单击。Swing。嗯,这是一个很大的应用程序,现在有很多类。我试图删掉重要的东西。游戏引擎和客户端之间的多线程工作正常。我试着硬编码这个动作。当我尝试等待GUI时出现问题。我只是不确定应该等待什么以及应该在哪里得到通知。所以基本上我需要帮助来实现这个注释:Move waitForPickedMove()和通知somhow。。。与movePicked()中的不完全一样,您能给我展示一下您的方法的简单示例吗?我想我不明白。多线程是很难的,除非你能很好地理解它。:)我的意思是,例如,一个简单的应用程序,其中两个线程互相等待,每个线程都等待单击鼠标,例如,将光标坐标写入控制台。您的设计先验地将一个播放器耦合到一个线程,这就是问题所在。在IClient中放置一个方法,当对方玩家移动时调用该方法;这可以是一个void
方法(一个经典回调)。游戏引擎还拥有一个回调方法,可以接收玩家的移动。人类玩家不需要自己的线程——它响应GUI上的操作。计算机播放器也不是线程:它可以在内部使用线程进行处理。当调用其“对方玩家移动”方法时,它向ExecutorService提交任务,ExecutorService计算。。。。。。移动并调用相应的游戏方法。感谢福克斯的解释,现在我将尝试实现你告诉我的。我会在这里写我的日志。好的,我已经完成了,它对PlayerClient有效。不幸的是,我在使用Runnable类(执行器服务)时仍然存在问题。我仍然收到这个非法的监视器