Bücher online kostenlos Kostenlos Online Lesen
Die Programmiersprache Ruby (German Edition)

Die Programmiersprache Ruby (German Edition)

Titel: Die Programmiersprache Ruby (German Edition) Kostenlos Bücher Online Lesen
Autoren: David Flanagan , Yukihiro Matsumoto
Vom Netzwerk:
und every zur Verzögerung
# von Codeblöcken definieren
# Beispiele:
#
# after 1 { puts "fertig" }
# every 60 { redraw_clock }
#
# Beide Methoden geben Thread-Objekte zurück. Rufen Sie kill für die
# zurückgegebenen Objekte auf, um die Codeausführung auszusetzen.
#
# Beachten Sie, dass dies eine sehr naive Implementierung ist.
# Eine robustere Implementierung würde einen einzelnen,
# globalen Timer-Thread für alle Aufgaben verwenden, würde
# eine Möglichkeit bieten, den Wert eines verzögerten Blocks
# zu erhalten, und würde eine Möglichkeit bereitstellen, auf die
# Fertigstellung aller anstehenden Aufgaben zu warten.
#
# Block nach Schlaf für angegebene Sekundenzahl ausführen
def after(seconds, &block)
Thread.new do # In einem neuen Thread ...
    sleep(seconds) # zuerst schlafen
    block.call # dann den Block aufrufen
end # Das Thread-Objekt sofort zurückgeben
end
# Wiederholt schlafen und dann den Block ausführen
# Dem Block beim ersten Aufruf einen Wert übergeben
# Bei weiteren Aufrufen den Wert der vorherigen Aufrufs zuweisen
def every(seconds, value=nil, &block)
Thread.new do # In einem Thread ...
    loop do # Endlosschleife (bis break im Block)
     sleep(seconds) # Schlafen
     value = block.call(value) # Und Block aufrufen
    end # Dann wiederholen
end # every gibt den Thread zurück.
end
    Listing 8.1 Die Methoden every und after
    8.8.2 Thread-Sicherheit mit synchronisierten Blöcken
    Beim Schreiben von Programmen, die mehrere Threads verwenden, ist es wichtig zu verhindern, dass zwei Threads nicht versuchen, dasselbe Objekt zur selben Zeit zu modifizieren. Eine Möglichkeit, um das zu erreichen, besteht darin, den Thread-sicher zumachenden Code in einem Block zu platzieren, der mit einem Aufruf der
synchronize
-Methode eines
Mutex
-Objekts verknüpft ist. Auch dies wird detailliert in „9.9 Threads und Parallelität“ besprochen. In Listing 8.2 führen wir das einen Schritt weiter und emulieren Javas Schlüsselwort
synchronized
mithilfe einer globalen Methode namens
synchronized
. Diese
synchronized
-Methode erwartet ein einzelnes Objektargument und einen Block. Sie besorgt sich ein mit dem Objekt verknüpftes
Mutex
und verwendet
Mutex.synchronize
, um den Block aufzurufen. Der schwierige Teil besteht darin, dass mit Ruby-Objekten, anders als mit Java-Objekten, kein
Mutex
verknüpft ist. Deshalb definiert Listing 8.2 auch eine Instanzmethode namens
mutex
in
Object
. Interessanterweise verwendet die Implementierung dieser
mutex
-Methode
synchronized
in seiner neuen Schlüsselwort-Form!
    require 'thread' # Ruby 1.8 enthält Mutex in dieser Bibliothek
# Das mit dem Objekt o verknüpfte Mutex erhalten und den Block
# dann unter dem Schutz dieses Mutex ausführen.
# Dies funktioniert wie das Schlüsselwort synchronized von Java.
def synchronized(o)
o.mutex.synchronize { yield }
end
# Object.mutex existiert in Wirklichkeit noch nicht. Wir müssen
# es definieren. Diese Methode gibt für jedes Objekt ein
# eindeutiges Mutex zurück und gibt für jedes spezifische
# Objekt immer dasselbe Mutex zurück. Mutexe werden nur
# bei Bedarf erzeugt und benötigen daher Synchronisation
# für Thread-Sicherheit.
class Object
# Das Mutex für dieses Objekt zurückgeben und erzeugen,
# falls nötig. Der schwierige Teil besteht darin, sicherzustellen,
# dass zwei Threads dies nicht gleichzeitig aufrufen und so
# zwei verschiedene Mutexe erzeugen.
def mutex
    # Wenn dieses Objekt schon ein Mutex hat, zurückgeben.
    return @__mutex if @__mutex

    # Andernfalls müssen wir ein Mutex für das Objekt erzeugen.
    # Aus Sicherheitsgründen müssen wir mit unserem Klassenobjekt
    # synchronisieren.
    synchronized(self.class) {
     # Erneut prüfen: Während wir in diesen synchronisierten Block
     # eingetreten sind, könnte ein anderer Thread bereits das Mutex
     # erzeugt haben.
     @__mutex = @__mutex || Mutex.new
    }
    # Der Rückgabewert ist @__mutex.
end
end
# Die oben definierte Methode Object.mutex muss die Klasse
# sperren, wenn das Objekt noch kein Mutex hat. Wenn die
# Klasse noch kein eigenes Mutex hat, wird die Klasse der
# Klasse (das Objekt Class) gesperrt. Um endlose Rekursion zu
# vermeiden, müssen wir sicherstellen, dass das Objekt Class
# ein Mutex hat.
Class.instance_eval { @__mutex = Mutex.new }
    Listing 8.2 Einfache synchronized-Blöcke

8.9 Fehlende Methoden und fehlende Konstanten
    Die Methode
method_missing
ist ein wichtiger Teil von Rubys Methoden-Lookup-Algorithmus (siehe „7.8 Methoden-Lookup“ ) und

Weitere Kostenlose Bücher