【问题标题】:How to use JButtons to Start and Pause SwingWorker thread如何使用 JButtons 启动和暂停 SwingWorker 线程
【发布时间】:2014-04-29 17:11:44
【问题描述】:

我正在尝试学习 Swing 中的线程。

我有一个带有 JProgressBar(进度)、五个 JButton(开始、暂停、恢复、取消、关闭)和一个 JLabel(label1)的 Frame。

框架打开。仅启用启动。 Start 调用我的班级 Progressor:

一劳永逸地再次更新

进步者进步者; //声明为类变量,在构造函数中初始化new,并在重写的done方法中再次初始化

这是 ButtonListener 类:

public class ButtonListener implements ActionListener{
    public void actionPerformed(ActionEvent e)
    {

        if (e.getSource() == jbStart) {
            progressor.execute();
            label1.setText("Progressing ...");
            jbCancel.setEnabled(true);
            jbResume.setEnabled(true);
            jbSuspend.setEnabled(true);
            jbClose.setEnabled(true);
        }
        if(e.getSource() == jbCancel) {
            progressor.cancel(true);
            label1.setText("Progress Canceled");
        }
        if (e.getSource() == jbSuspend) {
            label1.setText(progressor.suspendProgress());
        }
        if (e.getSource() == jbResume) {
            label1.setText(progressor.resumeProgress());
        }
        if (e.getSource() == jbClose) {
            dispose();
        }

    }

}//按钮监听器

这是 SwingWorker 类:

public class Progressor extends SwingWorker<Void, Integer> {

    private volatile boolean suspend = false;
    private Object lock = new Object();

    @Override
    protected Void doInBackground() {

        for (int i = 0; i <= 10; i++) {
            checkForSuspend();
            try {
                Thread.sleep(1000);
            }
            catch (InterruptedException e) {
            }
            publish(i);
        }   
        return null;
    }

    @Override
    protected void process(List<Integer> list) {
        int value = list.get(list.size() - 1);
        progress.setValue(value);

    }

    public void checkForSuspend() {
        synchronized (lock) {
            while (suspend) {
                try {
                    lock.wait();
                } catch (InterruptedException ie){
                }
            }
        }
    }//checkForSuspend

    @Override
    protected void done() {
        label1.setText("All Done.  Press close to exit");
        progressor = new Progressor();
    }

    public synchronized String suspendProgress() {
        suspend = true;
        return "Progress suspended ...";
    }

    public synchronized String resumeProgress() {
        synchronized (lock) {
            suspend = false;
            lock.notify();
            return "Progress resumed ...";
        }
    }


}//Progressor class

除了cancel 没有实际取消线程(进度条继续)之外,一切正常。

我应该在取消之前暂停它吗?

【问题讨论】:

    标签: java multithreading swing


    【解决方案1】:

    这个How to Pause and Resume a Thread in Java from another Thread 问题看起来与您的问题非常相似,并且在答案中有一些很好的例子。

    至于你自己的代码以及为什么它不起作用:

    1. 每次点击都会创建一个新进度条。您应该使用和控制一个,而不是每次都创建新的。
    2. 当暂停您的进度器完成工作而不是暂停时。正如上述问题所述 - 您应该在计算的某些点查看标志并对其采取行动。示例:

      while (!cancel) {
          if (!suspended) {
              for (int i = 1; i <= 10; i++) {
                      Thread.sleep(1000);
                      publish(i);
              }
          }
      }
      

      上面的代码将在下一次达到 10 时暂停(除非您在此之前恢复它),并在您按取消时结束(取消需要以明显的方式作为额外标志添加)。

    【讨论】:

    • 感谢您的链接,但我认为 SwingWorker 只能使用一次。我在哪里以及如何创建一个用按钮来控制?
    • @MayNotBe 事实上,SwingWorker 就像任何线程一样,不能多次调用execute()。这个想法是创建并执行一次(可能在您的表单初始化中,或者您第一次按开始时),然后在该执行中查看控制标志
    • 我不知道。我这样做了 - 在按钮侦听器之外创建了进度器并使用了您建议的代码,但它仍然无法正常工作。取消适用于 p.cancel(true);但这就像线程在进行时没有检查标志。
    • @MayNotBe 你能发布更新的代码吗?只是提醒一下,线程只会在计数 10 时挂起,即如果您在 3 处挂起,在挂起之前它仍然会计数到 10
    • 我刚刚在原始问题中发布了更新的代码。你是对的,当然它不会打断for。但是如何中断for 循环来检查suspend?当然,为什么我需要for?我可以在 while 循环中递增,它会每次都检查!
    【解决方案2】:

    您的线程应该在一个 while 循环中运行,该循环会寻找一个布尔值来更改另一个对象的值,然后在您单击按钮时只需使用 setPause(true/false) 更改状态:

    while(true){
        if(object_everyone_can_reference.getPause()){
        Thread.sleep(1000);
         }
    
     }
    

    【讨论】:

      猜你喜欢
      • 2013-02-10
      • 1970-01-01
      • 2012-01-22
      • 2017-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多