Die Erstellung von Java-Threads ist teuer, da einiges an Arbeit erforderlich ist:
- Für den Thread-Stack muss ein großer Speicherblock zugewiesen und initialisiert werden.
- Es müssen Systemaufrufe durchgeführt werden, um den nativen Thread beim Host-Betriebssystem zu erstellen / zu registrieren.
- Deskriptoren müssen erstellt, initialisiert und zu JVM-internen Datenstrukturen hinzugefügt werden.
Es ist auch in dem Sinne teuer, dass der Thread Ressourcen bindet, solange er lebt. zB der Thread-Stapel, alle vom Stapel aus erreichbaren Objekte, die JVM-Thread-Deskriptoren, die systemeigenen Thread-Deskriptoren des Betriebssystems.
Die Kosten für all diese Dinge sind plattformspezifisch, aber auf keiner Java-Plattform, auf die ich jemals gestoßen bin, sind sie billig.
Eine Google-Suche ergab für mich einen alten Benchmark , der eine Thread-Erstellungsrate von ~ 4000 pro Sekunde auf einem Sun Java 1.4.1 auf einem 2002er Dual-Prozessor Xeon mit 2002er Vintage Linux angibt. Eine modernere Plattform liefert bessere Zahlen ... und ich kann die Methodik nicht kommentieren ... aber sie gibt zumindest einen Überblick darüber, wie teuer die Erstellung von Threads wahrscheinlich ist.
Das Benchmarking von Peter Lawrey zeigt, dass die Thread-Erstellung heutzutage absolut gesehen erheblich schneller ist, aber es ist unklar, wie viel davon auf Verbesserungen in Java und / oder dem Betriebssystem zurückzuführen ist ... oder auf höhere Prozessorgeschwindigkeiten. Seine Zahlen deuten jedoch immer noch auf eine mehr als 150-fache Verbesserung hin, wenn Sie einen Thread-Pool verwenden und nicht jedes Mal einen neuen Thread erstellen / starten. (Und er macht den Punkt, dass dies alles relativ ist ...)
(Das oben Gesagte setzt "native Threads" anstelle von "grünen Threads" voraus, aber moderne JVMs verwenden aus Leistungsgründen alle native Threads. Grüne Threads sind möglicherweise billiger zu erstellen, aber Sie zahlen in anderen Bereichen dafür.)
Ich habe ein bisschen gegraben, um zu sehen, wie der Stapel eines Java-Threads wirklich zugewiesen wird. Im Fall von OpenJDK 6 unter Linux wird der Thread-Stack durch den Aufruf zugewiesen pthread_create
, der den nativen Thread erstellt. (Die JVM pthread_create
übergibt keinen vorab zugewiesenen Stapel.)
Dann wird innerhalb pthread_create
des Stapels durch einen Aufruf mmap
Folgendes zugewiesen :
mmap(0, attr.__stacksize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
Entsprechend bewirkt man mmap
das MAP_ANONYMOUS
Flag, dass der Speicher auf Null initialisiert wird.
Obwohl es möglicherweise nicht unbedingt erforderlich ist, dass neue Java-Thread-Stapel (gemäß der JVM-Spezifikation) auf Null gesetzt werden, werden sie in der Praxis (zumindest mit OpenJDK 6 unter Linux) auf Null gesetzt.