首先,我知道有几个关于我的问题的主题,而且我读了很多......我发现的最好的是来自Java Docu(link),我试图调整他们的解决方案。
但不幸的是,我的小生命游戏程序并没有像预期的那样工作......当我暂停模拟游戏的线程(将下一代绘制到JPanel)时,它按预期停止,然后我尝试恢复,没有任何反应(没有例外,没有机会调试)。我当然可以做的是,完全停止线程并创建一个新的,然后作为暂停/恢复... 我不想使用这种解决方法,因为我想了解我创建的问题,其次我想以不同的方式使用启动线程;)
所以这里是产生线程的代码(我主要使用volatile和synchronized):
public class MainJFrame extends JFrame {
private static final long serialVersionUID = 1L;
private JPanelGrid jPanelGrid;
private volatile Thread simulation;
private volatile boolean threadSuspended;
private JMenuBar menuBar;
private JMenu main;
public MainJFrame() {
jPanelGrid = new JPanelGrid(995, 770);
getContentPane().add(jPanelGrid);
initMenuBar();
setJMenuBar(menuBar);
pack();
setTitle("Conrads Game of Life");
setSize(1000, 800);
setLocationRelativeTo(null); // displayed in the middle of the screen
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public void startSimulation() {
//jPanelGrid.reset();
threadSuspended = false;
simulation = new Thread() {
@Override
public void run() {
Thread thisThread = Thread.currentThread();
while (simulation == thisThread) { //this check is for the correct stop of the thread
try {
Thread.sleep(50);
if(threadSuspended){ //this additional if is a performance tweak regarding Java Docu
synchronized (this) { //this part should be for the pause and resume feature
while (threadSuspended) {
wait();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
jPanelGrid.paintNextGen(); //Do I access it incorrectly?
}
}
};
simulation.start();
}
public synchronized void stopSimulation() {
simulation = null;
notifyAll();
}
public synchronized void pauseResume(){
threadSuspended = !threadSuspended;
if(!threadSuspended){
notifyAll();
}
}
private void initMenuBar(){
menuBar = new JMenuBar();
main = new JMenu("Main");
menuBar.add(main);
JMenuItem pauseResume = new JMenuItem("Pause/Resume");
pauseResume.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
pauseResume();
}
});
main.add(pauseResume);
JMenuItem start = new JMenuItem("Start");
start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
startSimulation();
}
});
main.add(start);
JMenuItem stop = new JMenuItem("Stop");
stop.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
stopSimulation();
}
});
main.add(stop);
}
}
答案 0 :(得分:1)
主要问题
您正在跨不同的线程共享threadSuspended
变量。您正在通过synchronized
,但保护它,您正在同步不同的对象。
synchronized (this)
< - 此处this
是Thread
个对象,请尝试使用 JFrame.this
public synchronized void pauseResume(){
< - 此处您正在同步JFrame
对象
编辑:删除了有关双重检查的部分,您正在使用volatile
,因此在发布Java 5.0后,我认为此代码应该没问题。有关详细信息,请参阅https://en.wikipedia.org/wiki/Double-checked_locking。