我继承了一个项目,我们在这个项目中使用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.");
}
}
}
这是单线程执行程序服务的任务吗?我似乎无法找到很多关于停止任务但仍继续使用相同线程的信息(例如我认为的状态模式)。如果可能的话,我不想开发一堆线程。
答案 0 :(得分:1)
问题可能是SwingWorker中完成的工作不可中断,即在doInBackground()中没有检查Thread.interrupted()。因此,即使您取消了工作人员,它实际上并没有停止,但仍会继续产生结果(最终被抛弃)。
可能解决此问题的一种方法是修改代码(很可能是detectEdges()内部)以及时响应中断。
如果这不是一个可行的选择,请更改方法。如果那里有活跃的工人,请跟踪;如果是,请将新参数集提交给它,否则启动一个。然后,工作程序本身需要修改,只有在生成与当前参数匹配的结果后才退出doInBackground()。这种方法可能更容易手动实现,即不使用SwingWorker。