スケジュールSwingWorkerのスレッド
-
06-09-2019 - |
質問
私は、リスト上の各要素に対して操作を行うには2リストを埋めるために、自分のスイングアプリケーションに1を実行するためのプロセス、および1つを持っています。私だけのタスクを実行している間、ロックアップGUIを停止するSwingWorkerのスレッドの中に2つのプロセスを移動した、と私はいくつかのリストにこの一連の操作を行う必要がありますので、その同時実行が最初に悪い考えではないでしょう場所。しかし、私はちょうど走ったとき
fillList.execute();
doStuffToList.execute();
空のリスト(当たり前...)上で実行するdoStuffToListスレッド。どのように私は最初の1が完了するまで待機するように第二の方法を教えてください?私が思う私はちょうど巣最初の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
}
}
}
}
...
}
他のヒント
どのように私は最初の1が完了するまで待機するように第二の方法を教えてください?私が思う私はちょうど巣最初の1の終わりに第二の方法をことができますが、私は知らない、それは悪い習慣のように思える。
あなたの代わりに呼び出し可能と先物を使用してに見たことがありますか? (..離れて全体のSwingWorkerの事業から、彼らは(代わりに、実際のリストの)Future.get(上doStuffToListの仕事をさせるので、GETが呼び出されたとき、それは準備ができているよ)この種のもののために良い試合のように聞こえますこの提案ではなく、答え)
を考えてみましょう私たちはこのようなものを持っています:
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が実際に含まれているため、IMO、すべてのハードがものを理解するために、非常に単純です。
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のを使用しての代わりに、デフォルトの1(これは、我々は、単一のアプリケーションのために必要なスレッドプールの数を減らすことができます。)しかし、我々はSwingWorkerExecutorを導入しました本当の理由は、それがSwingWorkerのの取り扱いを簡素化し、標準化するということでしたが実行さまた、成功とエラー条件とは、あなたが通常のために必要となる定型の束があるあなたが見ることができるように(私はあなたが知っている確信しているとして、彼らはシングルスレッドであれば。ずっと簡単です、)ユニットテストのためのロジックを置き換えることができますすべての単一のSwingWorkerの内部)(行われ、その代わりにということで、私たちはコールバックに働く)(行って移動します。
の側の利益は、チェーン内の複数のSwingの労働者を実行しているようなものは、実装が非常に簡単になるということです。
順次二つのプロセスを実行するには、伝統的にあなただけの他の後に1つのメソッドを呼び出します(!)。
fillList();
doStuffToList();
それとも、何かます:
doStuffToList(fillList());
あなたが一度に一つを処理している場合は、、あなたは間BlockingQueue
を持つ2つのスレッドをお勧めします。あなたは、複数のDO-スタッフのスレッドを持つことで、さらに行くかもしれない。
限りAWTイベントディスパッチスレッド(EDT)のように、それだけでブロックせずにアクションを分社だ、と後に通知されます懸念してます。