Java多线程暂停
我的目标 我是java多线程的新手,我正在尝试创建pong。我将只在这里包含一点与问题相关的代码 问题 我想通过按空格键暂停游戏,然后再按空格键继续游戏。以下代码用于暂停游戏,但无法继续。未来所有按键都无法识别。似乎主线程正在暂停 代码 主类Java多线程暂停,java,multithreading,Java,Multithreading,我的目标 我是java多线程的新手,我正在尝试创建pong。我将只在这里包含一点与问题相关的代码 问题 我想通过按空格键暂停游戏,然后再按空格键继续游戏。以下代码用于暂停游戏,但无法继续。未来所有按键都无法识别。似乎主线程正在暂停 代码 主类 public class MainManager { private Ticker ticker; private Thread tickerThread; private boolean active; public
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();
}
}
}
}
股票类
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类
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();
}
}
}
}
注意:该类被添加到在MainManager构造函数内部构造的JFrame中。如果这个JFrame类对我的问题很重要,我会发布代码,请告诉我
如何让
勾选器读取暂停并按键继续?欢迎任何其他批评。您从未离开Swing事件调度线程
您的股票代码在另一条线程中愉快地滴答作响,运行良好。但是,如果我们遵循您的切换调用的路径,它将永远不会到达另一个线程
按下空格键->Swing EDT witchcraft->按键->manager.toggleState()->ticker.pause()现在我们与manager同步,这并不难。我们还在主线上!然后我们等待
按下空格键->暂停Swing EDT。在另一个线程中运行的ticker的唯一部分是run方法
您希望在EDT之外运行与游戏逻辑相关的所有内容。在JFrame和事件处理程序的不同线程中运行MainManager和Ticker,并同步或使用锁定的布尔值将数据从IO线程发送到逻辑线程。您的notify()
应包含在同步块中。您的active
布尔值应包含volatile
关键字,对于原子性。在同步块中添加notify()
不会产生任何影响。在if(e.getKeyCode()==KeyEvent.VK_SPACE){
行上方的keyListener中,如果我放入System.out.println(“Hello”);
它只在暂停前打印,即使我一直单击空格键,也不会在暂停后打印。调用wait()时,您正在挂起事件调度线程(Event dispatch thread)),因为它位于来自KeyListener(在EDT上调用)的调用链中。当然,这会终止任何进一步的事件分派;notify()只能来自KeyEvent,但这也是正在等待来自自身的通知的线程。决不能调用wait()在EDT上。@MouseEvent volatile对修改布尔值的原子性没有任何作用。它确实提供了可视性。@ryangoldtein我不确定我应该改变什么,当涉及到基本以外的任何东西时,我真的是java的超级高手。所以我对swing、线程、事件处理程序和同步知之甚少。