2012-12-03 49 views
1

好吧我正在模拟运行。我在我的模拟的GUI上实现了两个JButton,它们是actionListeners。我想要的是让整个模拟暂停,如果我按下暂停按钮,并恢复,如果我按下恢复按钮。如何使用Swing暂停Java仿真

有多个线程正在运行,并且我试图获取每个线程并在点击暂停按钮时调用它们的wait()方法,但是我没有成功这样做。

因此,我需要一些建议如何做到这一点。我为GUI使用Swing,并且侦听器正常工作。我确实尝试在View类的当前线程(使用MVC模式)上调用sleep()和wait()以查看发生了什么,但导致整个应用程序崩溃。

任何想法?

回答

3

您需要为模拟线程提供额外的逻辑,它将接受来自控制(GUI)线程的“信号”并等待下一个控制信号恢复执行。

例如,您可以在仿真线程中使用volatile boolean isPaused实例字段。将其设置为true/false以暂停/恢复仿真线程。在仿真线程执行相应的逻辑:

public void run() { 
    while (true) { 
     simulate(); 
     while (isPaused) { 
      Thread.sleep(100); 
     } 
    } 
} 
+2

这个解决方案的问题是线程将每100毫秒唤醒一次,这会使用处理器时间。最好使用'wait()'和'notify()',它没有这个问题。 – durron597

+0

我认为等待/通知对于非常并发的环境更好。对于他的简单任务,这个解决方案可以完成这项工作。 – hoaz

0

我想你可以创建一个ThreadGroup来存储所有的线程,然后尝试使用

ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();

顺便说一句,ExecutorService是一个不错的选择,太多。

0

使用共享对象的两个类之间进行通信。然后让你的gui在点击按钮时设置状态对象的值,并在再次点击时再次更改它。下面是一些示例代码:

public class Simulation implements Runnable { 
    private State myState = null; 

    public Simulation(State myState) { 
    this.myState = myState; 
    } 

    public void run() { 
    while(myState != null) { 
     if (myState.isPaused()) myState.wait(); 
     // Do other stuff 
    } 
    } 
} 

public class MainClass implements ActionListener() { 
    private State myState = new MyState(); 

    private void beginSimulation() { 
    Simulation s = new Simulation(this.myState()); 
    new Thread(s).start(); 
    } 

    public void actionPerformed(ActionEvent e) { 
    if(myState.isPaused()) { 
     myState.setPaused(false); 
     myState.notify(); 
    } else { 
     myState.setPaused(true); 
    } 
    } 
} 

public class MyState() { 
    private boolean paused = false; 
    public MyState(boolean paused) { this.paused = paused; } 
    public boolean getPaused() { return paused; } 
    public void setPaused(boolean paused) { this.paused = paused; } 
} 
2

如果动画使用Swing的Timer简单的答案是调用stop()

我强烈建议使用Timer进行动画制作,因为它可以确保动作在EDT上执行。

+0

反过来说,如果OP有一个问题中所述的模拟,那么在EDT上运行它是一个坏主意,因为模拟往往会导致处理器沉重并导致应用程序成为无响应。 –