Nous avons quelque chose comme ceci:
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);
}
Ceci est assez simple, l'OMI, parce que dans notre cas, le SwingWorkerExecutor contient en fait tout le mal à comprendre des choses:
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);
}
}
}
}
}
Il existe des interfaces manquantes Il devrait être assez simple d'écrire sans les voir ici. Notre véritable déploiement SwingWorkerExecutor s'exécute en utilisant un ExecutorService injecté au lieu de celui par défaut (cela réduit le nombre de pools de threads dont nous avons besoin pour une seule application). Mais la vraie raison pour laquelle nous avons introduit SwingWorkerExecutor était qu'il simplifiait et standardisait la gestion des SwingWorker conditions de succès et d'erreur et permet également de remplacer la logique pour les tests unitaires (qui, comme je suis sûr que vous le savez, sont beaucoup plus simples si elles sont à un seul thread.Comme vous pouvez le voir, il y a un tas de messages standards dont vous auriez normalement besoin pour chaque SwingWorker à l'intérieur de done(), donc au lieu de cela, nous déplaçons le travail done() dans un callback.
L'avantage secondaire est que l'exécution de plusieurs travailleurs Swing dans une chaîne devient très facile à mettre en œuvre.
Des sons comme un BlockingQueue peuvent être utiles (http://java.sun.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html). –