Toolradar

Multi-Threading in Commons Lang 3.0

Oliver Heger

Seit einiger Zeit arbeitet das Apache-Commons-Team an der runderneuerten Version 3.0 der weit verbreiteten Bibliothek Commons Lang. Vor kurzem ist eine erste Betaversion erschienen. Dieser Artikel nimmt einige Neuerungen dieser Version unter die Lupe.

Die Mission des Commons-Lang-Projekts [1] ist die Bereitstellung von Funktionalität, die so grundlegend ist, dass man sie eigentlich im JDK selbst erwarten würde. Bisher wurde strikt auf Kompatibilität mit älteren Java-Versionen geachtet. Mit der kommenden Version 3.0 ändert sich dies: Sie benötigt Java 1.5 oder höher, nutzt neue Sprachmittel und bietet auch Hilfsklassen für einige der neueren Packages. Dieser Artikel legt den Fokus auf neue Funktionalität zur nebenläufigen Programmierung, die einen Schwerpunkt der neuen Version ausmacht. Eine umfassendere Vorstellung der Neuerungen in Commons Lang 3.0 finden Sie online [2].

Fiel die Unterstützung für Threads in älteren Java-Versionen noch recht rudimentär aus, bietet Java 1.5 in dieser Beziehung deutlich mehr. Daran angelehnt beinhaltet Commons Lang 3.0 ein neues Package namens concurrent mit Hilfsfunktionen zu dieser Thematik.

Eine nützliche Klasse aus diesem Package ist BasicThreadFactory, eine Implementierung des ThreadFactory-Interface. JDK-Klassen, die eigenständig Threads erzeugen, können mit einem solchen Objekt konfiguriert werden. BasicThreadFactory sorgt dafür, dass die erzeugten Threads gewisse Eigenschaften haben, z. B. einen vorgegebenen Namen oder eine bestimmte Priorität.

ConcurrentUtils enthält diverse allgemeine Hilfsfunktionen zur nebenläufigen Programmierung. Einen Schwerpunkt bildet dabei die Behandlung der häufig von JDK-Klassen geworfenen ExecutionException: In Abhängigkeit des ursächlichen Fehlers kann hier entsprechend reagiert werden.

Eine weitere Gruppe von Klassen aus dem concurrent Package behandelt die Erzeugung von Objekten unter konkurrierendem Zugriff. Die Klasse LazyInitializer implementiert das so genannte Double-Check-Idiom für Instanzfelder, das bereits im Java Magazin vorgestellt wurde [3]. Sie erlaubt das Aufschieben der Erzeugung eines Objekts bis zu seiner tatsächlichen Nutzung und sorgt dabei für eine korrekte Synchronisation. Die Klasse AtomicInitializer funktioniert analog, setzt aber zu ihrer Implementierung auf atomare Variablen aus dem java.util.concurrent.atomic Package, was je nach Anwendungsfall effizienter sein kann.

Die Klasse BackgroundInitializer erzeugt ein Objekt in einem eigenen Hintergrund-Thread, während sich der Aufrufer mit anderen Dingen beschäftigen kann. Erst wenn das zu erzeugende Objekt wirklich gebraucht wird, erfolgt ein Aufruf der get()-Methode. get()blockiert so lange, bis die Initialisierung komplett abgeschlossen ist. Folgendes Beispiel zeigt eine spezielle BackgroundInitializer-Implementierung zum Anlegen einer JPA EntityManagerFactory:

public class DBInitializer extends BackgroundInitializer {
    protected EntityManagerFactory initialize() {
        return Persistence.createEntityManagerFactory("mypersistenceunit");
    }
}

Eine Anwendung erzeugt gleich zu Beginn eine Instanz dieser Klasse und startet die Initialisierung. Später fragt sie das Ergebnis über einen Aufruf der get()-Methode ab:

DBInitializer init = new DBInitializer();
init.start();  // start the background thread

// now do some other stuff
.
EntityManagerFactory factory = init.get();
Fazit

Die Betaversion von Commons Lang 3.0 ermöglicht einen Ausblick auf die neuen Features der Bibliothek. Zwar kann sich bis zur finalen Version noch etwas ändern, größere Umstrukturierungen sind aber eher unwahrscheinlich. Das Projekt bleibt seiner Mission weiterhin treu und bietet nützliche Hilfen nun auch für moderne Java-Versionen.

Oliver Heger arbeitet als Softwareentwickler und -architekt bei Agfa HealthCare im Bereich Clinical Research Solutions. Er ist außerdem Committer und PMC-Mitglied im Apache-Commons-Projekt.
Geschrieben von
Oliver Heger
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.