My Goal
我是java中多线程的新手,我正在尝试创建pong。我只会在此处包含一些与问题相关的代码。
Problem
我希望能够通过按空格键暂停游戏,然后通过按空格键再次恢复游戏。以下代码可以暂停游戏,但无法恢复。以后所有的按键都不会被识别。看起来好像主线程正在暂停。
Code
主类
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();
}
});
}
}
股票代码类
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
暂停和恢复?有其他批评欢迎指正。
最佳答案
您从未离开过 Swing 事件调度线程。
您的股票在另一个线程中愉快地滴答作响,工作正常。但是,如果我们遵循您的切换调用的路径,它永远不会到达另一个线程。
你的空格键被按下->Swing EDT巫术->keyPressed->manager.toggleState()->ticker.pause() 现在我们与Manager同步,这并不难。我们仍然在主线程上!然后我们等待。
您的空格键被按下 ->Swing EDT 已暂停。在另一个线程中运行的代码的唯一部分是 run 方法。
您希望在 EDT 之外运行与游戏逻辑相关的所有内容。在与 JFrame 和事件处理程序不同的线程中运行 MainManager 和 Ticker,并同步或使用锁定的 boolean 值将数据从 IO 线程发送到逻辑线程。
关于Java多线程暂停,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30603740/