在java中取消并重用(SwingWorker)线程

时间:2015-06-24 18:23:10

标签: java multithreading swing

我继承了一个项目,我们在这个项目中使用java并在图像上绘制内容。当用户来回移动滑块以改变图像边缘的阈值时,它会运行一种检测此方法的方法。这需要200-300ms,因此它会将UI锁定一点但是当用户移动滑块时,它会不断地锁定界面。

他们似乎已将此移动到后台线程,但每次滑块移动时它都会创建一个新线程。因此,当用户将滑块移动一英寸时,它会生成80个线程,整个系统会锁定几秒钟。

我不确定如何解决这个问题。它是一个回复到UI的回旋工线程。我尝试取消()然后再次执行()线程,但看起来不可能。当我可以取消旧的线程时,我不想要很多线程(因为我们不需要旧预览),所以我认为只有一个可以工作。

这是工作线程。

// WORKER
private class ThresholdWorker extends SwingWorker<BufferedImage, Object> {
    // long-running code to be run in a worker thread
    @Override
    public BufferedImage doInBackground() throws Exception {
        @SuppressWarnings("static-access")
        BufferedImage img = new BufferedImage(imagePanel.rect_width, imagePanel.rect_height, BufferedImage.TYPE_3BYTE_BGR);
        img = imagePanel.detectEdges();
        return img;
    } // end method doInBackground

    // code to run on the event dispatch thread when doInBackground returns
    @Override
    protected void done() {
        try {
            @SuppressWarnings("static-access")
            BufferedImage Img = new BufferedImage(imagePanel.rect_width, imagePanel.rect_height, BufferedImage.TYPE_3BYTE_BGR);
            Img = get();
            imagePanel.standardRectEdgesDilated = Img;
            imagePanel.repaint();
        } catch (InterruptedException ignore) {
        } catch (ExecutionException ex) {
            IdentiFrog.LOGGER.writeException(ex);
            System.err.println("Error encountered while performing calculation.");
        }
    }
}

这是单线程执行程序服务的任务吗?我似乎无法找到很多关于停止任务但仍继续使用相同线程的信息(例如我认为的状态模式)。如果可能的话,我不想开发一堆线程。

1 个答案:

答案 0 :(得分:1)

问题可能是SwingWorker中完成的工作不可中断,即在doInBackground()中没有检查Thread.interrupted()。因此,即使您取消了工作人员,它实际上并没有停止,但仍会继续产生结果(最终被抛弃)。

可能解决此问题的一种方法是修改代码(很可能是detectEdges()内部)以及时响应中断。

如果这不是一个可行的选择,请更改方法。如果那里有活跃的工人,请跟踪;如果是,请将新参数集提交给它,否则启动一个。然后,工作程序本身需要修改,只有在生成与当前参数匹配的结果后才退出doInBackground()。这种方法可能更容易手动实现,即不使用SwingWorker。