Java多线程暂停

时间:2015-06-02 18:25:05

标签: java multithreading

  

我的目标

我是java中的多线程新手,我正在尝试创建pong。我只会在这里提供一些与问题相关的代码。

  

问题

我希望能够通过按空格键暂停游戏,然后再按空格键再次恢复。以下代码用于暂停游戏,但无法恢复。未来的所有按键都无法识别。好像主线程暂停了。

  

代码

主要类

public class MainManager {

    private Ticker ticker;
    private Thread tickerThread;

    private boolean active;

    public MainManager() {
        ticker = new Ticker(this,10);
        tickerThread = new Thread(ticker);

        tickerThread.start();
    }

    public synchronized void tick() {
        // Does necesary things for each game tick
    }

    public void toggleState() {
        if (this.active) {
            ticker.pause();
        } else {
            this.setActive(true);
            notify();
        }
    }

    public void setActive(boolean b) {
        this.active = b;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
                    @Override
                   public void run() {
                        MainManager manager = new MainManager();
                   }
        });
    }
}

Ticker Class

public class Ticker implements Runnable {

    private MainManager manager;
    private int tick;

    public Ticker(MainManager manager,int tick) {
        this.manager = manager;
        this.tick = tick;
    }

    @Override
    public void run() {
        manager.setActive(true);
        while (true) {
            try {
                Thread.sleep(this.tick);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            manager.tick();
        }
    }

    public void setTickSpeed(int speed) {
        this.tick = speed;
    }   

    public synchronized void pause() {
        synchronized(manager) {
            try {
                System.out.println("Waiting for Manager");
                manager.setActive(false);
                manager.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

KeyListener类

注意: 此类添加到在MainManager构造函数内构造的JFrame中。如果这个JFrame类对我的问题很重要,我会发布代码,让我知道

public class KeyboardListener implements KeyListener {

    private MainManager manager;

    public KeyboardListener(MainManager manager) {
        this.manager = manager;
    }

    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println("KeyPressed);
        //This line only prints on the first spacebar. 
        //After the game is paused, it never prints again.  Despite me spamming spacebar
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            manager.toggleState();
        }
    }
}

如何通过按键让tickerThread暂停和恢复?任何其他批评都是受欢迎的。

1 个答案:

答案 0 :(得分:2)

你从未离开过Swing Event Dispatch Thread。

你的股票代码正在另一个线程中快速地打勾,工作正常。但是,如果我们按照您的切换调用的路径,它永远不会到达另一个线程。

你的太空键被按下了 - > Swing EDT巫术 - > keyPressed-> manager.toggleState() - > ticker.pause()现在我们与Manager同步,这并不困难。我们还在主线上!然后我们等。

按下空格键 - > Swing EDT暂停。您在另一个线程中运行的自动收报机的唯一部分是run方法。

您希望运行与您的游戏逻辑关闭 EDT相关的所有内容。在与JFrame和事件处理程序不同的线程中运行MainManager和Ticker,并同步或使用锁定的布尔值将数据从IO线程发送到逻辑线程。