我有一个资源密集的应用程序,它使用大图像作为输入,这些图像上的一些操作可能需要一段时间。因此,我希望让一些部件在自己的线程中运行。为此,我使用以下代码首先测试:
Thread t1 = new Thread(new Runnable() {
public void run()
{
inputChooser.setFileFilter(filter);
inputChooser.addChoosableFileFilter(filter);
int img = inputChooser.showOpenDialog(this);
if (img == JFileChooser.APPROVE_OPTION) {
File file = inputChooser.getSelectedFile();
String filename = file.getName();
if (filename.contains("B10")) {
greenBand = 1;
}
if (filename.contains("B20")) {
greenBand = 2;
}
if (filename.contains("B30")) {
greenBand = 3;
}
if (filename.contains("B40")) {
greenBand = 4;
}
if (filename.contains("B50")) {
greenBand = 5;
}
if (filename.contains("B60")) {
greenBand = 6;
}
if (filename.contains("B70")) {
greenBand = 7;
}
try {
greenImage = ImageIO.read(file);
ImageIO.write(greenImage, "JPEG", new File("img2_tmp.jpeg"));
greenImage = ImageIO.read(new File("img2_tmp.jpeg"));
if (greenImage.getWidth() > 8000 | greenImage.getHeight() > 7000) {
greenImage = greenImage.getSubimage(1450, 1400, (greenImage.getWidth()-3200), (greenImage.getHeight()-3000));
}
update(greenImage, greenIcon, greenLabel);
loadingBar.setIndeterminate(false);
checkInput();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Input Image Error", "Input Error", WARNING_MESSAGE);
}
}
}});
t1.start();
当我运行应用程序时,它会在调用此代码时冻结。但是,我已经设法让它工作一次,我不确定如何但它完美运行(不是第一次,它先冻结几次然后随机工作一次)。我没有改变任何代码只是一些缩进,以便让它适应其余的代码,因为它只是继续冻结。按下按钮动作按下调用此方法,上面的代码就是按下按钮时冻结的。
有没有理由说明为什么会这样?
提前致谢
答案 0 :(得分:3)
您正在同时从两个线程(新创建的主线程和主线程)调用非线程安全的代码(swing(非线程安全))。
确保在创建新线程之前已经解耦逻辑。
对于这个特定的用例,我建议您使用SwingWorker
代替线程,它们易于使用,并且在摆动限制内工作良好。
有关http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
的SwingWorker
的更多信息
希望这有帮助。
祝你好运。
答案 1 :(得分:1)
很难确切地说,但我注意到变量greenImage
和greenBand
未在任何地方声明。这让我觉得它们是全局变量。如果其他内容可以访问它们,那么它们可能导致某些操作将您的代码发送到无限循环或其他意外的坏事。