Java暂停后无法恢复线程

时间:2015-02-05 12:42:30

标签: java multithreading

首先,我知道有几个关于我的问题的主题,而且我读了很多......我发现的最好的是来自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);
}

}

1 个答案:

答案 0 :(得分:1)

主要问题

您正在跨不同的线程共享threadSuspended变量。您正在通过synchronized保护它,您正在同步不同的对象。

synchronized (this)< - 此处thisThread个对象,请尝试使用 JFrame.this

public synchronized void pauseResume(){< - 此处您正在同步JFrame对象


编辑:删除了有关双重检查的部分,您正在使用volatile,因此在发布Java 5.0后,我认为此代码应该没问题。有关详细信息,请参阅https://en.wikipedia.org/wiki/Double-checked_locking