繁体   English   中英

如何在继续当前线程之前等待事件发生?

[英]How to wait for an event to happen before continuing the current thread?

我正在编写一个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

当我在线程上等待时,我最喜欢的是使用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

您可以通过两种方法来执行此操作,但到目前为止,最简单的方法是使用观察者模式创建事件侦听器。 该模式背后的思想是允许代码注册事件发生时要执行的动作,同时将事件处理程序与要调用的动作隔离开。 请注意,此解决方案不需要任何多线程。

如果您确实希望GUI和游戏逻辑在单独的线程上运行,那么您似乎正在尝试实现此处描述的锁定方法。 有几件事需要注意:

  • JVM可以随时出于任何原因为您提供一个等待线程InterruptedException 您应该始终检查导致您等待的情况,然后再继续。
  • 每当您访问线程间共享的状态时,都需要确保适当地使用了synchronized volatile
  • 锁定WINNER ,请记住,此字段可以更改。 如果Board锁定在WINNER并更改了其值,则进入Game的新线程将在Board块完成之前自由获得其锁定,因为它们锁定在不同的对象上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM