Java SWT GUI在长时间运行的后台进程中对更新无响应

时间:2012-05-28 15:31:50

标签: java multithreading swt

使用的技术 Java 1.6 SWT GUI

问题: 在运行后台任务大约60分钟后,GUI信息更新最终停止(GUI变得完全没有响应)。

问题似乎与GUI更新有关,我无法弄清楚如何解决这种情况(查看了Java并发选项等)。优化线程使用处理信息定期更新GUI中的文本框。在我的测试过程中,这个“更新”在控制台输出和数据库输出后面显着滞后 - 假设优化执行了4000个优化步骤。控制台可以报告优化步骤1900(在数据库中确认),但GUI仍然输出来自步骤700的信息。

背景信息 我正在运行机器学习优化任务,并将任务合并到SWT GUI中。根据参数,任务可能需要一个小时或更长时间才能完成。我将优化任务设计为单独的线程。 GUI允许用户按下按钮以启动优化。 GUI包括(以简化)1)任务表和2)用于在优化期间反馈的SWT文本框。每个不同的任务组完成后,任务表都会更新。 SWT文本框输出更多的常规/频繁反馈(非常类似于System.out但是使用线程通过GUI EDI线程更新文本框)。也就是说,我相信我至少使用了三个线程:1)GUI线程,2)用于GUI更新的aSync线程(SWT),以及3)用于优化本身的后台线程。 (我之所以提到这一点,是因为Java并发教程明确指出长时间运行的任务必须在自己的线程中运行,以避免GUI死锁和饥饿。但是,即使我认为我这样做,GUI仍然在经过长时间的优化运行后停止 - 这就是我要解决的问题。由于优化运行需要很长时间才能完成,因此GUI失速是一个主要问题 - 在实现GUI停滞之前会丢失一个多小时。)

基本程序结构: GUI类 - >为优化类

启动一个单独的线程

优化类可以通过回调

更新GUI类组件(使用SWT asyncExec

证实: 我可以确认后台线程完全运行 - 1)后台线程更新了几个数据库表,所有表都完全更新; 2)System.out直接从发送到Eclipse中的控制台的优化任务输出,显示优化线程完全完整地运行。

此外,在测试期间,如果我将优化集缩减到大约400步,那么GUI似乎运行正常。

相关代码: GUI CLASS-- 用于更新GUI和GUI类的代码(由优化类线程调用) -

public void setFeedback(final String workerthreadinfo, final boolean append) {
try{  
    Display.getDefault().asyncExec(new Runnable(){  
    public void run(){  
        if(!textfeedback.isDisposed() && textfeedback !=null){  
        if (append) {
                      textfeedback.setText(workerthreadinfo + "\n" +
                            textfeedback.getText()) ;
        } else {
            textfeedback.setText(workerthreadinfo) ;
        }  
         } 
    }  
    });
     } .....

在GUI类中实例化优化工作线程

private OptimizerWorkerThread workerthread = 
   new OptimizerWorkerThread(this) ;

GUI类中的代码启动优化类(作为线程)

protected void optimize() {
    workerthread.go() ;
}

优化课程 - 优化线程方法“链接”到GUI(guiwindow =上面的GUI类)

// ==================================================================
// GUI Update Methods
// ================================================================== 
public void updateFeedBackInfo(String update, boolean append) {
    guiwindow.setFeedback(update, append) ;
}

从优化线程回调GUI的示例

//GUI Feedback
this.updateFeedBackInfo("Saving optimization run record to database ... ", 
   APPENDTEXT ) ; // APPENDTEXT = boolean TRUE instructing GUI textbox to append

2 个答案:

答案 0 :(得分:1)

这听起来不像是线程问题。

如果你在GUI线程中意外运行,那么点击按钮后GUI就会死机。所以我认为我们可以排除这种情况。

您所描述的内容更像是内存负载/性能问题。我强烈建议将Visualvm与您的应用程序连接,并特别注意不断增加内存消耗。同样使用visualvm中包含的探查器可能会暗示消耗大量CPU或内存的东西。

答案 1 :(得分:1)

解决方案附录:

在此应用程序的最终测试期间,我更仔细地确定了GUI的明显来源减慢。通过GUI减速,我的意思是复制2500个文件之间的区别。缓慢的问题需要将近20分钟才能完成复制。应用此修复后,完全相同的文件复制时间不到1分钟。

问题 该副本通过工作线程处理。工作线程定期更新GUI。此更新包括ProgressBar更新和文本框更新。

文本框更新似乎是问题的根源。我想要的是一个文本框PREPENDS状态更新信息 - 例如“复制文件C:/hello.txt” - 而不是追加(在SWT中可用)。为了创建一个虚假的前置我使用(在一个单独的线程中):

textfeedback.setText(workerthreadinfo + "\n" + textfeedback.getText()) ;

这段代码似乎是缓慢的罪魁祸首 - 可能很容易理解为什么。在每个文件副本上,复制整个文本框内容,然后将新信息添加到文本框中。在复制了大约700个文件之后,这开始陷入困境(你可以看到明显的减速)并且之后继续恶化。

修复,虽然我对它不满意,但是改为使用SWT TextBox append()方法。