Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SWT GUI在长时间运行的后台进程中对更新没有响应_Java_Multithreading_Swt - Fatal编程技术网

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

Java SWT GUI在长时间运行的后台进程中对更新没有响应,java,multithreading,swt,Java,Multithreading,Swt,使用的技术: Java 1.6 SWT图形用户界面 问题: 后台任务运行大约60分钟后,GUI信息更新最终停止(GUI变得完全无响应) 问题似乎出在GUI更新上,我不知道如何纠正这种情况(查看了Java并发选项等)。优化线程使用处理信息定期更新GUI中的文本框。在我的测试过程中,这个“更新”明显落后于控制台输出和数据库输出——假设优化执行了4000个优化步骤。控制台可能会报告优化步骤1900的工作(在数据库中确认),但GUI仍然会输出步骤700的信息 背景信息: 我正在运行一个机器学习优化任务,

使用的技术: Java 1.6 SWT图形用户界面

问题: 后台任务运行大约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更新(SWT)的
aSync
线程,以及3)用于优化本身的后台线程。(我之所以提到这一点,是因为Java并发性教程明确指出,长时间运行的任务必须在自己的线程中运行,以避免GUI死锁和饥饿。然而,尽管我认为我这样做了,但GUI在长时间优化运行后仍然会停滞——这就是我试图解决的问题。因为优化运行需要很长时间才能完成,GUI暂停是一个主要问题——在意识到GUI暂停之前损失了一个多小时。)

基本程序结构: GUI类-->为优化类启动单独的线程

优化类可以通过回调更新GUI类组件(使用SWT
asyncExec

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

此外,在测试期间,如果我将优化集缩减到大约400个步骤,GUI似乎运行良好

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

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

private OptimizerWorkerThread workerthread = 
   new OptimizerWorkerThread(this) ;
GUI类中启动优化类的代码(作为线程)

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

从优化线程回调GUI的示例

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

这听起来不像是线程问题

如果您意外地在GUI线程中运行,那么在单击按钮后,GUI将立即失效。所以我想我们可以排除这种可能性


您所描述的内容听起来更像是内存负载/性能问题。我强烈建议将Visualvm与您的应用程序连接起来,并特别注意不断增加的内存消耗。另外,使用visualvm中包含的探查器可能会提示一些消耗大量cpu或内存的内容。

解决方案附录:

在这个应用程序的最终测试期间,我更仔细地确定了GUI速度减慢的明显原因。所谓GUI慢下来,我指的是复制2500个文件之间的区别。慢下来的问题需要将近20分钟才能完成拷贝。应用修复程序后,复制完全相同的文件不到1分钟

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

文本框更新似乎是问题的根源。我想要的是一个文本框,它在状态更新信息前面加上前缀,比如“copyingfilec:/hello.txt”,而不是append(在SWT中提供)。要创建我使用的人造前置词(在单独的线程中):

这段代码似乎是导致速度减慢的罪魁祸首——而且很容易看出原因。在每个文件副本上,都会复制整个文本框内容,然后将新信息添加到文本框中。在复制了大约700个文件后,这种情况开始停滞(你可以看到明显的减速),并在之后继续恶化


修复方法是使用SWT TextBox append()方法,尽管我对此不满意。

可能代码示例中没有包含该方法,但您实际上在哪里告诉SWT重新绘制组件?我没有在SWT中明确地重新绘制。
protected void optimize() {
    workerthread.go() ;
}
// ==================================================================
// GUI Update Methods
// ================================================================== 
public void updateFeedBackInfo(String update, boolean append) {
    guiwindow.setFeedback(update, append) ;
}
//GUI Feedback
this.updateFeedBackInfo("Saving optimization run record to database ... ", 
   APPENDTEXT ) ; // APPENDTEXT = boolean TRUE instructing GUI textbox to append
textfeedback.setText(workerthreadinfo + "\n" + textfeedback.getText()) ;