1

使用するテクノロジー: Java 1.6 SWT GUI

問題: バックグラウンド タスクを約 60 分間実行した後、GUI 情報の更新が最終的に停止します (GUI が完全に応答しなくなります)。

問題は GUI の更新にあるようで、この状況を解決する方法がわかりません (Java の同時実行オプションを確認するなど)。最適化スレッドは、GUI のテキスト ボックスを処理情報で定期的に更新します。私のテスト中、この「更新」はコンソール出力とデータベース出力より大幅に遅れています。つまり、最適化が 4000 の最適化ステップを実行すると仮定します。コンソールは、最適化ステップ 1900 (データベースで確認済み) に取り組んでいると報告する場合がありますが、GUI はまだステップ 700 からの情報を出力します。

背景情報: 機械学習の最適化タスクを実行しており、そのタスクを SWT GUI に組み込んでいます。パラメータによっては、タスクの実行が完了するまでに 1 時間以上かかる場合があります。最適化タスクを別のスレッドとして設計しました。GUI により、ユーザーはボタンを押して最適化を開始できます。GUI には (簡素化するために) 1) タスクの表と 2) 最適化中のフィードバック用の SWT テキスト ボックスが含まれています。タスクのテーブルは、個別のタスク グループが完了するたびに更新されます。SWT テキスト ボックスは、より定期的/頻繁なフィードバックを出力します (ただしSystem.out、スレッド化を使用して GUI EDI スレッドを介してテキスト ボックスを更新するのとよく似ています)。つまり、少なくとも 3 つのスレッドを使用していると思います。1) GUI スレッド、2) aSyncGUI 更新 (SWT) 用のスレッド、3) 最適化自体用のバックグラウンド スレッドです。(これについて言及するのは、Java 並行処理のチュートリアルでは、GUI のデッドロックと枯渇を回避するために長時間実行されるタスクを独自のスレッドで実行する必要があることを明確に指示しているためです。これは私が修正しようとしているものです. 最適化の実行が完了するまでに非常に長い時間がかかるため、GUI のストールは大きな問題です.GUI がストールしていることに気付くまでに 1 時間以上かかります.)

基本的なプログラム構造: GUI クラス --> 最適化クラス用に別のスレッドを起動

asyncExec最適化クラスは、コールバックを介して( SWT を使用して) GUI クラス コンポーネントを更新できます。

確認済み: バックグラウンド スレッドが完全に実行されていることを確認できます。1) バックグラウンド スレッドがいくつかのデータベース テーブルを更新し、すべてのテーブルが完全に更新されています。2) System.outEclipse のコンソールに送信された最適化タスクからの直接の出力は、最適化スレッドが完全かつ完全に実行されていることを示しています。

さらに、テスト中に最適化セットをおそらく 400 ステップに縮小すると、GUI は正常に動作するように見えます。

関連コード: GUI クラス -- 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() ;
}

OPTIMIZATION CLASS -- 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
4

2 に答える 2

1

ソリューションの補遺:

このアプリケーションの最終テスト中に、GUI の速度低下の明らかな原因をより注意深く特定しました。GUI のスローダウンとは、2500 個のファイルをコピーすることの違いを意味します。スローダウンの問題により、コピーを完了するのに約 20 分かかりました。修正を適用すると、まったく同じファイルのコピーに 1 分もかかりませんでした。

問題 コピーはワーカー スレッドを介して処理されます。ワーカー スレッドは定期的に GUI を更新します。この更新には、ProgressBar の更新とテキスト ボックスの更新が含まれます。

テキスト ボックスの更新が問題の原因のようです。私が欲しかったのは、ステータス更新情報 (「ファイル C:/hello.txt をコピーしています」など) を追加するのではなく、前置するテキスト ボックスでした (SWT で利用可能)。私が使用した偽のプリペンドを作成するには(別のスレッドで):

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

この小さなコードが速度低下の原因であるように思われますが、その理由はおそらく簡単にわかります。ファイルをコピーするたびに、テキスト ボックスの内容全体がコピーされ、新しい情報がテキスト ボックスの先頭に追加されます。約 700 個のファイルをコピーした後、これは動きが鈍くなり (速度低下が目に見えてわかります)、その後も悪化し続けます。

私は満足していませんが、代わりに SWT TextBox の append() メソッドを使用することで修正できます。

于 2012-08-02T19:54:51.993 に答える
1

これはスレッド化の問題とは思えません。

GUI スレッドで誤って実行すると、ボタンをクリックした直後に GUI が機能しなくなります。したがって、それを除外できると思います。

あなたの説明は、メモリ負荷/パフォーマンスの問題のように聞こえます。Visualvm をアプリケーションに接続することを強くお勧めします。特に、絶えず増加するメモリ消費に注意してください。また、visualvm に含まれているプロファイラーを使用すると、大量の CPU やメモリを消費している可能性があります。

于 2012-05-28T17:51:12.377 に答える