Im 10. Teil habe ich das Thema fachliche Transaktionen gestreift. Wie man technisch damit umgeht, hatte ich seinerzeit offen gelassen. In diesem Post wollen wir darauf zurückkommen. Sehen Sie sich als Einstieg bitte das folgende Codefragment an:

tasksView.clearSelection();
for (Task task : tasks) {
  new DeleteTaskWorker(task, tasksModel, tasksDelegate)
      .execute();
}
updateCategories();

In einer Schleife werden Worker instanziiert und ausgeführt. Das Löschen besteht aus einem Serviceaufruf sowie im Erfolgsfall der Manipulation eines Bedienelements (Entfernen aus der Liste). Die Methode updateCategories() zählt, wie oft Kategorien in Aufgaben verwendet werden. Das darf sie natürlich erst, wenn alle Löschoperationen abgeschlossen wurden. Dumm nur, dass obiger Quelltext dies nicht garantiert… Die Lösung des Problems besteht darin, solange zu warten, bis alle Worker ihre Arbeit abgeschlossen haben, und erst danach die Methode aufzurufen. Wie nicht anders zu erwarten, hält Java (mindestens) eine Lösung in den unendlichen Weiten seiner Klassenbibliothek parat: java.util.concurrent.CountDownLatch. Diese Synchronisierungshilfe erlaubt einem oder mehreren Threads so lange zu warten, bis eine bestimmte Anzahl an Operationen in anderen Threads vollständig abgearbeitet wurde. Hierzu wird ein CountDownLatch mit der Anzahl der Operationen initialisiert. Durch den Aufruf der Methode await() wartet der Aufrufer-Thread auf die Abarbeitung der Aufgaben. Korrespondierende Worker rufen hierzu am Ende ihrer Verarbeitung countDown() auf.


This is a (slightly updated) repost of a piece I published on my blog Tommi’s Blog. I deleted the blog in the wake of the GDPR, so the original version is no longer available, or only through the WayBack Machine of the Internet Archive. Please note: code usually has not been updated, so language feature reflect the time the original post was written.