2

Swing アプリケーションで実行するプロセスが 2 つあります。2 つのプロセスを Swingworker スレッドに移動して、タスクの実行中に GUI がロックするのを防ぎました。また、この一連の操作を複数のリストに対して実行する必要があるため、最初の段階では同時実行は悪い考えではありません。場所。しかし、私がちょうど走ったとき

fillList.execute();
doStuffToList.execute();

空のリストで実行される doStuffToList スレッド (duh...)。最初のプロセスが完了するまで待機するように 2 番目のプロセスに指示するにはどうすればよいですか? 最初のプロセスの最後に2番目のプロセスをネストすることもできると思いますが、それは悪い習慣のようです。

4

4 に答える 4

1

最初のプロセスが完了するまで待機するように 2 番目のプロセスに指示するにはどうすればよいですか? 最初のプロセスの最後に2番目のプロセスをネストすることもできると思いますが、それは悪い習慣のようです。

代わりに呼び出し可能オブジェクトと先物を使用することを検討しましたか? これらは、swingworker ビジネス全体を除けば、この種のこと (実際のリストではなく Future.get() で doStuffToList を機能させるため、get が呼び出されたときに準備が整う) に適しているように思えます.. (これは答えではなく提案と考えてください)

于 2009-05-27T15:10:09.793 に答える
1

このようなものがそれを行うと思いますか?

boolean listIsFull=false;
class FillListWorker extends SwingWorker<Foo,Bar>
{
    ...
    protected void done()
    {
        synchronized (listYouveBeenFilling)
        {
            listIsFull=true;
            listYouveBeenFilling.notifyAll();
        }
    }
    ...
}

class DoStuffToListListWorker extends SwingWorker<Foo,Bar>
{
    ...
    protected Foo doInBackground()
    {
        synchronized (listYouveBeenFilling)
        {
            while (!listIsFull)
            {
                try
                {
                    listYouveBeenFilling.wait();
                }
                catch (InterruptedException ie)
                {
                    // Don't worry, we'll just wait again
                }
            }
        }
    }
    ...
}
于 2009-05-27T14:16:40.260 に答える
0

次のようなものがあります。

private SwingWorkerExecutor swingWorkerExecutor;

//...

protected void runChain(List<SwingWorker<Void>> chainWorkers,
                        final SwingWorkerExecutor.RunAfter<Void> runAfter,
                        final SwingWorkerExecutor.RunOnError runOnError)
{
    final List<SwingWorker<Void>> remainingWorkers =
        chainWorkers.subList(1, chainWorkers.size());
    SwingWorkerExecutor.RunAfter<Void> chainRunAfter;
    if (chainWorkers.size() > 1)
    {
        chainRunAfter = new SwingWorkerExecutor.RunAfter<Void>()
        {
            @Override
            public void run(Void value)
            {
                runChain(remainingWorkers, runAfter, runOnError);
            }
        };
    }
    else
    {
        chainRunAfter = runAfter;
    }

    currentWorker = chainWorkers.get(0);

    swingWorkerExecutor.execute(currentWorker, chainRunAfter, runOnError);
}

私たちの場合、 SwingWorkerExecutor には実際には理解しにくいものがすべて含まれているため、これは非常に単純です。

public class DefaultSwingWorkerExecutor implements SwingWorkerExecutor
{
    @Override
    public <T> void execute(SwingWorker<T, ?> worker, RunAfter<T> after,
                            RunOnError onError)
    {
        worker.addPropertyChangeListener(
            new RunAfterHandler<T>(worker, after, onError));
        worker.execute();
    }

    private static class RunAfterHandler<T> implements PropertyChangeListener
    {
        private final SwingWorker<T, ?> worker;
        private final RunAfter<T> after;
        private final RunAfter<Throwable> onError;

        protected RunAfterHandler(SwingWorker<T, ?> worker, RunAfter<T> after,
                                  RunOnError onError)
        {
            this.worker = worker;
            this.after = after;
            this.onError = onError;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt)
        {
            if ("state".equals(evt.getPropertyName()) &&
                evt.getNewValue() == SwingWorker.StateValue.DONE)
            {
                if (worker.isCancelled())
                {
                    return;
                }

                try
                {
                    after.run(worker.get());
                }
                catch (InterruptedException e)
                {
                    Thread.currentThread().interrupt();
                }
                catch (ExecutionException e)
                {
                    onError.run(e);
                }
            }
        }
    }
}

欠けているインターフェースがいくつかありますが、ここで見なくても簡単に書くことができます。

実際のデプロイ SwingWorkerExecutor は、デフォルトの ExecutorService ではなく、注入された ExecutorService を使用して実行されます (これにより、1 つのアプリに必要なスレッド プールの数が減ります)。しかし、SwingWorkerExecutor を導入した本当の理由は、SwingWorker の成功とエラーの処理を簡素化し、標準化するためです。また、単体テストのロジックを置き換えることもできます (ご存知のように、シングル スレッドの場合ははるかに簡単です)。その代わりに、done() の作業をコールバックに移動します。

副次的な利点は、複数の Swing ワーカーをチェーンで実行するなどの実装が非常に簡単になることです。

于 2010-04-12T05:09:06.767 に答える