у нас есть что-то вроде этого:
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);
}
Это довольно просто, IMO, потому что в нашем случае 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);
}
}
}
}
}
Есть некоторые недостающие интерфейсы, которые h должен быть довольно прямолинейным, чтобы писать, не видя их здесь.
Наше настоящее развертывание SwingWorkerExecutor выполняется с использованием внедренного ExecutorService вместо стандартного (это уменьшает количество пулов потоков, которые необходимы для одного приложения). Но настоящая причина, по которой мы ввели SwingWorkerExecutor, заключалась в том, что она упрощает и стандартизирует обработку SwingWorker и условия ошибки, а также позволяет заменить логику модульных тестов (которые, как я уверен, вы знаете, намного проще, если они однопоточные.) Как вы можете видеть, есть куча шаблонов, которые вам обычно нужны для каждого SwingWorker внутри done(), поэтому вместо этого мы перемещаем работу done() в обратный вызов.
Боковое преимущество заключается в том, что такие вещи, как запуск нескольких рабочих Swing в цепочке, становятся довольно простыми в реализации.
Похоже, что BlockingQueue может быть полезным (http://java.sun.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html). –