La creazione di thread Java è costosa perché è coinvolto un bel po 'di lavoro:
- Un grande blocco di memoria deve essere allocato e inizializzato per lo stack di thread.
- È necessario effettuare chiamate di sistema per creare / registrare il thread nativo con il sistema operativo host.
- I descrittori devono essere creati, inizializzati e aggiunti alle strutture dati interne alla JVM.
È anche costoso nel senso che il filo limita le risorse finché è vivo; ad esempio lo stack di thread, tutti gli oggetti raggiungibili dallo stack, i descrittori di thread JVM, i descrittori di thread nativi del sistema operativo.
I costi di tutte queste cose sono specifici della piattaforma, ma non sono economici su nessuna piattaforma Java che abbia mai incontrato.
Una ricerca su Google mi ha trovato un vecchio punto di riferimento che riporta una velocità di creazione di thread di ~ 4000 al secondo su un Sun Java 1.4.1 su un Xeon dual vintage del 2002 con Linux vintage 2002. Una piattaforma più moderna fornirà numeri migliori ... e non posso commentare la metodologia ... ma almeno fornisce un campo di battaglia per quanto sia probabile la costosa creazione di thread.
Il benchmarking di Peter Lawrey indica che la creazione di thread è significativamente più veloce in questi giorni in termini assoluti, ma non è chiaro quanto di ciò siano dovuti miglioramenti in Java e / o nel sistema operativo ... o velocità del processore più elevate. Ma i suoi numeri indicano ancora un miglioramento di oltre 150 volte se si utilizza un pool di thread rispetto alla creazione / avvio di un nuovo thread ogni volta. (E sottolinea che questo è tutto relativo ...)
(Quanto sopra presuppone "thread nativi" anziché "thread verdi", ma i JVM moderni utilizzano tutti thread nativi per motivi di prestazioni. I thread verdi sono probabilmente più economici da creare, ma si paga in altre aree.)
Ho fatto un po 'di ricerche per vedere come viene realmente allocato lo stack di un thread Java. Nel caso di OpenJDK 6 su Linux, lo stack di thread viene allocato dalla chiamata a pthread_create
quello che crea il thread nativo. (La JVM non passa pthread_create
uno stack preallocato.)
Quindi, all'interno pthread_create
dello stack viene assegnato da una chiamata mmap
come segue:
mmap(0, attr.__stacksize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
Secondo man mmap
, il MAP_ANONYMOUS
flag fa inizializzare la memoria a zero.
Pertanto, anche se potrebbe non essere essenziale che i nuovi stack di thread Java siano azzerati (secondo le specifiche JVM), in pratica (almeno con OpenJDK 6 su Linux) sono azzerati.