我正在编写一个GUI游戏,我想等到游戏结束,然后才能回归获胜者。但是,由于我的游戏管理器类与用于实现游戏逻辑并检测到胜利的类是分开的,我想知道如何让游戏管理器等到另一个类通知它获胜,然后继续做其他的东西。我以前在多线程方面并没有太多工作,所以我希望有人可以解释我是如何实现这一点的。
以下是来自GameManager类的一些相关代码'我试过的主要内容:
...
Game game = new Game(mode);
String winner = game.getWinner();
...
从Game类:
public Game(Game.Mode mode){
this.board = new Board(7);
window = new BoardFrame(7, 7, mode, board); //Graphical interface
window.setVisible(true);
}
public String getWinner(){
synchronized(board.WINNER){
try {
board.WINNER.wait();
} catch (InterruptedException e) {}
}
return board.WINNER;
}
董事会成员:
public boolean update(int num){
if (isValidMove(CurrentPlayer, num)){
buttonClients.get(positions.get(CurrentPlayer)).clear();
positions.put(CurrentPlayer, num);
board[num] = 1;
buttonClients.get(num).performCallback(CurrentPlayer);
if ((WINNER = isGameFinished())!=""){
//Disable all further inputs
for (int i = 0; i<board.length; i++){
board[i] = 1;
}
synchronized (WINNER) {
WINNER.notify();
}
}
CurrentPlayer = (CurrentPlayer==PLAYER1)?PLAYER2:PLAYER1;
return true;
}
return false;
}
编辑:所以我找到了屏幕显示问题的原因,即GameManager的所有代码都在EventQueue.invokeLater()
块中。我现在已经把它从那个块中拿出来了,现在屏幕显示正常。但是,当我玩到最后,synchronized(WINNER)
块最终运行时,似乎没有任何反应?换句话说,游戏继续等待WINNER
。
答案 0 :(得分:1)
当我在线程上等待时,我最喜欢的是使用CountDownLatch
并使用Callable<V>
并将其提交给线程执行器,该线程执行器返回Future<V>
块直到线程完成。
public class Example {
ExecutorService executorService = Executors.newCachedThreadPool();
public void init(){
CountDownLatch latch = new CountDownLatch(1);
Future<Boolean> submit = executorService.submit(new Thread3());
executorService.execute(new Thread1(latch, submit));
executorService.execute(new Thread2(latch));
}
public class Thread1 implements Runnable{
private CountDownLatch latch;
private Future<Boolean> thread3;
public Thread1(CountDownLatch latch, Future<Boolean> thread3) {
this.latch = latch;
this.thread3 = thread3;
}
@Override
public void run() {
int i = 0;
try {
thread3.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
while (i < 50){
LockSupport.parkNanos(1000);
i++;
}
latch.countDown();
}
}
public class Thread2 implements Runnable{
private CountDownLatch latch;
public Thread2(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
latch.await();
System.out.println("We can continue");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Thread3 implements Callable<Boolean>{
@Override
public Boolean call() throws Exception {
int i = 0;
while (i < 50){
LockSupport.parkNanos(1000);
i++;
}
return true;
}
}
}
良好的资源: http://tutorials.jenkov.com/java-concurrency/index.html
答案 1 :(得分:0)
有几种方法可以做到这一点,但到目前为止,最好的方法是使用observer pattern来创建事件监听器。这种模式背后的想法是允许代码在事件发生时注册要执行的操作,同时将事件处理程序与它要调用的操作隔离开来。请注意,此解决方案不需要任何多线程。
如果您确实希望您的GUI和游戏逻辑在不同的线程上运行,那么您似乎正在尝试实现here所述的锁定方法。需要注意以下几点:
InterruptedException
等待线程。在继续操作之前,您应该始终检查导致您等待的条件。synchronized
和volatile
。WINNER
的位置,请记住此字段可能会发生变化。如果在Board
上锁定了WINNER
并更改了其值,则在Game
块完成之前,输入Board
的新主题可以自由获取其锁定,因为他们可以使用temp=line[IndexEnd:IndexStart];
重新锁定不同的物体。