Die Programmiersprache Ruby (German Edition)
die Gesamtanzahl der heruntergeladenen Bytes ermitteln:
total = 0
download_threads.each {|t| total += t[:progress] }
Zusammen mit
[]
und
[]=
definiert
Thread
auch eine Methode
key?
, um zu prüfen, ob ein gegebener Schlüssel für einen Thread existiert. Die Methode
keys
liefert ein Array mit Symbolen zurück, die für den Thread definiert sind. Dieser Code könnte besser wie folgt geschrieben werden, so dass er auch mit Threads funktioniert, die noch nicht losgelaufen sind und daher noch keinen Schlüssel
:progress
definiert haben:
total = 0
download_threads.each {|t| total += t[:progress] if t.key?(:progress)}
9.9.3 Thread Scheduling
Ruby-Interpreter müssen häufig mehr Threads ausführen, als CPUs zur Verfügung stehen. Wenn eine echte parallele Verarbeitung nicht möglich ist, wird sie durch das gemeinsame Nutzen einer CPU für mehrere Threads simuliert. Der Prozess dazu wird als Thread Scheduling bezeichnet. Je nach Implementierung und Plattform kann das Thread Scheduling vom Ruby-Interpreter durchgeführt oder durch das zugrunde liegende Betriebssystem übernommen werden.
9.9.3.1 Thread-Prioritäten
Der wichtigste Faktor, der das Thread Scheduling beeinflusst, ist die Thread-Priorität : Threads mit hoher Priorität werden gegenüber Threads mit niedriger Priorität bevorzugt. Genauer gesagt erhält ein Thread nur dann CPU-Zeit, wenn es keinen höher priorisierten Thread gibt, der auf Ausführungszeit wartet.
Das Setzen und Abfragen der Priorität eines
Thread
-Objekts in Ruby geschieht durch
priority=
und
priority
. Beachten Sie, dass es keine Möglichkeit gibt, die Priorität eines Threads zu setzen, bevor er mit der Ausführung beginnt. Ein Thread kann aber als erste Aktion seine eigene Priorität höher oder niedriger setzen.
Jeder neu erzeugte Thread beginnt mit der gleichen Priorität wie der Thread, der ihn erzeugt hat. Der Haupt-Thread beginnt mit einer Priorität von 0.
So wie viele andere Aspekte beim Threading sind Thread-Prioritäten abhängig von der Implementierung von Ruby und dem zugrunde liegenden Betriebssystem. Unter Linux zum Beispiel können unprivilegierte Threads ihre Prioritäten nicht erhöhen oder erniedrigen. Daher werden in Ruby 1.9 (das native Threads verwendet) unter Linux die Thread-Prioritäten ignoriert.
9.9.3.2 Thread-Präemptivität und Thread.pass
Wenn mehrere Threads mit der gleichen Priorität eine CPU gemeinsam nutzen müssen, liegt es am Thread Scheduler, zu entscheiden, wann und für wie lang jeder Thread ausgeführt wird. Manche Scheduler sind präemptiv, das heißt, dass ein Thread nur eine vorgegebene Zeitspanne laufen darf, bevor ein anderer Thread mit der gleichen Priorität an der Reihe ist. Andere Scheduler sind nicht präemptiv: Nachdem ein Thread mit der Ausführung begonnen hat, darf er laufen, bis er sich schlafen legt, wegen einer Ein-/Ausgabe-Aktion warten muss oder ein Thread mit höherer Priorität aufwacht.
Wenn ein lange laufender, rechenlastiger Thread (also einer, der niemals wegen I/O-Aktivitäten wartet) auf einem nicht präemptiven Scheduler läuft, lässt er andere Threads der gleichen Priorität »verhungern« und sie erhalten keine Chance, selbst ausgeführt zu werden. Um dies zu vermeiden, sollten lange laufende, rechenlastige Threads regelmäßig
Thread.pass
aufrufen, mit denen der Scheduler gebeten wird, einen anderen Thread aufzurufen.
9.9.4 Thread-Zustände
Ein Thread kann in Ruby in einem von fünf möglichen Zuständen sein. Die beiden interessantesten Zustände sind die für »aktive« Threads: Ein Thread, der aktiv ist, ist entweder ausführbar ( runnable ) oder schlafend ( sleeping ). Ein ausführbarer Thread ist einer, der gerade läuft oder bereit ist, das nächste Mal zu laufen, wenn die CPU ihm Ressourcen bereitstellt. Ein schlafender Thread ist einer, der schläft (siehe
Kernel.sleep
), der auf I/O wartet oder der sich selber gestoppt hat (siehe
Thread.stop
weiter unten). Threads wechseln typischerweise zwischen den Zuständen laufend und schlafend.
Es gibt zwei Zustände für Threads, die nicht mehr aktiv sind. Ein beendeter Thread wurde entweder normal beendet oder abrupt durch eine Exception abgebrochen.
Schließlich gibt es noch einen Übergangszustand. Ein abgeschossener (siehe
Thread.kill
weiter unten), aber noch nicht beendeter Thread wird als abbrechend ( aborting ) bezeichnet.
9.9.4.1 Thread-Zustände abfragen
Die Klasse
Thread
definiert eine Reihe von Instanzmethoden, um den Status eines Threads
Weitere Kostenlose Bücher