Groovy Closures – Aufräumen von Ressourcen

In den beiden ersten beiden Blogeinträgen zu Closures in Groovy habe ich eine kurze Einführung und eine nähere Beschreibung zum Verwendungszweck von Closures gegeben. In diesem Beitrag möchte ich gerne über das Execute-Around-Method Pattern und Coroutines schreiben.

In Java ist ja die automatische Garbage Collection ein zweischneidiges Schwert. Als Entwickler muss man sich nicht mehr um die Deallokation von Ressourcen kümmern. Allerdings hat man keine Garantie darüber, zu welchem Zeitpunkt die Ressource vom Garbage Collector freigegeben wird. Hin und wieder kann es vorkommen, dass man selbst darüber entscheiden möchte, wann eine Ressource freizugeben ist. Dafür gibt es die bekannten Methoden wie close() und destroy() die ressourcenintensive Klassen besitzen.

Jedoch kann es nun passieren, wenn man dem Entwickler die Kontrolle über das Entfernen lässt, dass dieser darauf vergessen könnte die entsprechende Methode aufzurufen. Closures könne dazu verwendet werden, dass der Aufruf einer ressourcenfreigebenden Methode gesichert wird. Zuerst noch ein Beispiel für das Vergessen eines Aufrufs der eine Ressource wieder freigeben sollte.

image

Diese Beispiel demonstriert das Erstellen eines FileWriters und der Versuch in das erstellte File zu schreiben. Da allerdings der Aufruf der close Methode vergessen wird, wird das entsprechende Zeichen nicht in das erstellte File geschrieben. Das nächste Beispiel verwendet die withWriter (Groovy-spezifisch) Methdoe, welche den geöffneten Stream zum File automatisch flusht und schließt, nach dem man vom Closure zurückgekehrt ist.

image

Im letzten Beispiel braucht man sich also über die Ressourcenfreigabe keine Gedanken zu machen und man kann sich auf seine eigentliche Aufgabe konzentrieren. Natürlich kann man diese Funktionalität seinen eigenen Klassen hinzufügen um den Entwickler das Arbeiten zu erleichtern.  Das folgende Beispiel zeigt eine Ressource-Klasse bei der der Entwickler nicht darauf achten muss, benutzte Ressourcen wieder freizugeben. Dabei kommt das Execute-Around-Method Pattern mit der Verwendung einer Closure zum Einsatz.

image

In der statischen Methode use wird eine Instanz von Resource erzeugt, auf der die Methode open und close aufgerufen wird. Die close Methode wird im finally Block ausgeführt was dazu führt, dass die Ressource auf jeden Fall wieder freigegeben wird auch wenn in der Closure eine Exception geworfen würde. Im folgenden Beispiel sieht man wie man die Resource-Klasse verwenden kann.

image

Die Angabe des Resource-Typs im Deklarationsteil der Closure ist nicht verpflichtend und kann auch weggelassen werden. Dank der Closure passiert der Aufruf von close automatisch, deterministisch und genau zum richtigen Zeitpunkt. Der Entwickler kann sich auf die Applikations-Domäne und deren inhärente Komplexität konzentrieren und überlässt Bibliotheken, System-Level Aufgaben wie z.B. dem garantierten Aufräumen von File I/O usw.

Closures und Coroutinen

Beim Aufruf einer Funktion oder Methode, wird ein neuer Gültigkeitsbereich (Scope) in der Ausführungsfolge des Programms erstellt. Man betritt dabei die Funktion an einem bestimmten Eintrittspunkt (am Beginn der Methode). Wenn man die Methode abgearbeitet hat, kehrt man zum Aufrufs-Gültigkeitsbereich (Caller’s Scope) zurück.

Coroutinen ermöglichen Funktionen mehrere Eintrittspunkte, wobei jeder an der Stelle fortsetzt, wo der letzte Aufruf suspendiert wurde. Man kann eine Methode betreten, einen Teil der Methode ausführen,  suspendiert dann den Aufruf und arbeitet im Aufrufer-Kontext oder -Gültigkeitsbereich anderen Code ab. Danach kann man wieder an der letzten Stelle der aufgerufenen Methode weiter arbeiten.

Coroutinen sind ganz gut geeignet, um spezielle Algorithmen oder Logik, z.B. das bekannte Consumer-Producer-Problem, umzusetzen. In Java kann man Coroutinen mit Hilfe von wait() und notify() in Kombination mit Multithreading implementieren. Closures dagegen, vermitteln den Eindruck, Coroutinen in einem Single-Thread auszuführen. Zum Beispiel:

image

In diesem Code springt die Kontrolle immer zwischen der iterate Methode und dem Closure hin und her. In der folgenden Abbildung kann der Output des Beispiels betrachtet werden.

image

In jedem Aufruf des Closures fährt man mit dem Wert von total des vorherigen Aufrufs fort. Es fühlt sich so an, als würde die Ausführungsreihenfolge zwischen zwei Methoden hin und her springen.

image

Im nächsten Blogbeitrag werde ich Curried und Dynamic Closures näher erläutern und wie man in einer Closure Werte bereits vorbinden kann und dadurch Code-Duplizierung vermeidet.

Über sageniuz

https://about.me/ClausPolanka
Dieser Beitrag wurde unter Programming veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s