4

SwingWorker を使用して一度に複数のことを行う小さな画像処理アプリケーションがあります。ただし、次のコード (簡略化された抜粋) を実行すると、JDK 7 b70 (Windows) ではハングしますが、6u16 では動作します。別のワーカー内で新しいワーカーを開始し、その結果を待ちます (実際のアプリは複数のサブワーカーを実行し、このようにずっと待機します)。ここで間違ったパターンを使用したのでしょうか (ほとんどの場合、swingworker-pool には 3 から 5 のワーカーがあり、10 の制限があると思います)。

import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Swing {
       static SwingWorker<String, Void> getWorker2() {
               return new SwingWorker<String, Void>() {
                       @Override
                       protected String doInBackground() throws Exception {
                               return "Hello World";
                       }
               };
       }
       static void runWorker() {
               SwingWorker<String, Void> worker 
                   = new SwingWorker<String, Void>() {
                       @Override
                       protected String doInBackground() throws Exception {
                               SwingWorker<String, Void> sw2 = getWorker2();
                               sw2.execute();
                               return sw2.get();
                       }
               };
               worker.execute();
               try {
                       System.out.println(worker.get());
               } catch (Exception e) {
                       e.printStackTrace();
               }
       }
       public static void main(String[] args) {
               SwingUtilities.invokeLater(new Runnable() {
                       @Override
                       public void run() {
                               runWorker();
                       }
               });
       }

}
4

4 に答える 4

6

まだ誰もリンクを公開していないため、これは実際には既知のバグのようです:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6880336

驚くべきことに、ほとんどの重要なアプリケーションにとって致命的なバグとなるはずのバグに対する投票数は 100 未満です。

于 2010-05-04T01:12:03.943 に答える
1

SwingWorker は SwingWorker スレッドで実行されます。だから見たら

sw2.get() でハングしているようで、jdk7 には swingworker という名前のスレッドが 1 つしかありません。jdk6 では、一度に 3 ~ 5 個表示されます。–kd304

これは、SwingWorker クラスがスレッドではなく、スレッドで実行されるタスクであり、Java 6 の SwingWorker の ExecutorService のデフォルト構成が Java 7 のものとは異なるためです。 SwingWorker クラス内) には、タスクに割り当てる最大スレッド数の値が異なります。

//From Java 6 SwingWorker

private static final int MAX_WORKER_THREADS = 10;

public final void execute() {
    getWorkersExecutorService().execute(this);
}

private static synchronized ExecutorService getWorkersExecutorService() {
...
private static synchronized ExecutorService getWorkersExecutorService() {
new ThreadPoolExecutor(0, MAX_WORKER_THREADS,
                                     1L, TimeUnit.SECONDS,
                                     new LinkedBlockingQueue<Runnable>(),
                                     threadFactory)
}

SwingWorker タスクを実行するスレッドは 1 つしかなく、最初のタスクは 2 番目のタスクの完了を待機していますが、2 番目のタスクが実行されるスレッドが 2 番目のタスクの完了を待機しているため、2 番目のタスクは実行できません。戻る前に。別のスレッドの実行に依存する swingworker スレッドを作成すると、確実にデッドロックに陥ります。ExecutorServiceを使用して、SwingWorker スレッドで実行されるイベントをスケジュールし、あるスケジュールされたイベントを別のスケジュールされたイベントの完了に依存させないようにすることをお勧めします。

Java 7 スウィングワーカー

于 2009-08-27T20:15:59.410 に答える
0

SwingWorker のソース コードを見ると、ExecutorService がワーカー スレッドのプールとして使用されているように見えます。使用される ExecutorService のタイプが Java 6 と Java 7 の間で変更された可能性があります。ExecutorService が一度に 1 つのスレッドしか管理しない場合、コードがデッドロックするようです (お気づきのようです)。

これは、「sw2.get()」呼び出しが現在のスレッドをブロックするためです。これは、sw2 が使用しようとするスレッドと同じです。最初のワーカーがブロックされているため、sw2 は決して実行できません。

最善の解決策は、このような Swing ワーカーのチェーンを呼び出さないようにロジックを変更することだと思います。

于 2009-08-27T16:56:48.610 に答える
-1

JDK update 18 より前は、以下を実行できました。

public static void main(String[] args) {

    new SwingWorker<Void, Void>() {
        @Override
        protected Void doInBackground() throws Exception {
            System.out.println("ok");
            return null;
        }
    }.execute();

}

SwingWorkers を EDT で実行する必要があるため、このコードは機能しなくなりました。

したがって、SwingWorkers をネストすることはできません (sw2 は、新しい JDK のサンプル コードでは決して実行されません)。

ネストされた swingWorkers を executorService java.util.concurrent.Future 呼び出しに置き換えることは、良い回避策だと思います。

于 2010-02-12T11:27:08.090 に答える