2011-09-25 17 views
11

私のコンピュータには4つのコアがあり、Java swing guiプログラムを実行しています。アプリケーションを実行すると、2つのコアと約30%のCPU使用率しか使用されません。私は処理するファイルが非常に多く、より多くのCPUを使用してこのタスクをより速く完了させるために、それらを2つのスレッドに分割したいと考えています。Swingworkerのインスタンスが同時に実行されていません

私は2つのintを持つコンストラクタを持つPrepareTask呼ばれるSwingWorkerのクラスを、持っている:

class PrepareTask extends SwingWorker<Void, Void> { 
    int start, end; 
    PrepareTask (int start, int end) { ... } 
    ... 
    public Void doInBackground() {... } 
    public void done() { ... } 

私はこのような2つのインスタンスを作成:(それが表示されます)の両方が起動されている

PrepareTask prepareTask = new PrepareTask(0,numberOfFiles/2); 
    prepareTask.execute(); 
    PrepareTask prepareTask2 = new PrepareTask(numberOfFiles/2, numberOfFiles); 
    prepareTask2.execute(); 

をが、それが実行されるとき、私は、最初の準備が完了しなければならないことを見ることができます(print stmts)。そして、CPU使用率は以前と同じ約30%です。どちらももちろん、同じソースのデータを取得します(DefaultTableModel)。

これを行う方法や私が間違っていることはありますか?ありがとう。

+0

処理時間の大部分がファイルアクセスに関係する場合、ディスクがボトルネックになるため、スレッドが多数あると必ずしも高速になるとは限りません。これらのファイルに対してさらに処理を行うことができますか? – jfpoilpret

答えて

16

これは、SwingWorkerの動作がJava 6アップデートから別のものに変更されたことによるものです。実際にJava 6の古いSUNバグデータベースにはバグレポートがあります。

元のSwingWorker実装をNスレッドから変更し、無制限キューを持つスレッドを1スレッドに変更しました。したがって、同時に2つのSwingWorkerを同時に実行させることはできません。 (デッドロックが発生するシナリオも作成されます。スイングワーカーが最初に待つ別のものを待っている場合、結果としてデッドロックが発生する可能性があります)。

これを回避するには、ExecutorServiceそれにFutureTasksを投稿します。これらはSwingWorker APIの99%を提供します(SwingWorkerはFutureTaskの派生物です)。実行者を正しく設定するだけで済みます。

+1

これまで説明してきましたが、ほとんどの場合よりも優れています。+1 –

+0

これはJava SE 6u21で修正されるはずです。http://www.oracle.com/technetwork/java/javase/bugfixes6u21- 156339.html – keuleJ

+0

これはバグです:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6925575 – keuleJ

0

多分、あなたのスレッドのスケジューリングを制御しているのでしょうか? SwingWorkerのスレッドプールサイズは1です(SwingWorkerのjavadocに複数のSwingWorkerスレッドを実行することについての記述はなく、複数のスレッドがSwingでいくつかの困難な並行性の問題を引き起こす可能性があります)。あなたがしたいすべてが並列に何らかの処理を実行している場合は

、 あなたがどんな変更でGUIを更新する 終わりSwingUtilities.invokeLater()を呼び出し、runを実施し、 のJava Threadクラスを拡張することで、この簡単な方法を解決することができます。

class PrepareTask extends Thread 
    { 
     PrepareTask (int start, int end) { ... } 
     public void run() { ... ; SwingUtilities.invokeLater(new Runnable() { public void run() { do any GUI updates here })} 
でスレッドを開始

:データモデルの中で何かがシングルTHREある

prepareTask.start(); 

それともadedと2番目のスレッドをブロックしますか? その場合、その問題をデータモデルで解決する必要があります。