La creación de hilos Java es costosa porque hay un poco de trabajo involucrado:
- Se debe asignar e inicializar un gran bloque de memoria para la pila de subprocesos.
- Se deben realizar llamadas al sistema para crear / registrar el hilo nativo con el sistema operativo host.
- Los descriptores deben crearse, inicializarse y agregarse a las estructuras de datos internas de JVM.
También es costoso en el sentido de que el hilo ata los recursos mientras esté vivo; por ejemplo, la pila de hilos, cualquier objeto accesible desde la pila, los descriptores de hilos JVM, los descriptores de hilos nativos del sistema operativo.
Los costos de todas estas cosas son específicos de la plataforma, pero no son baratos en ninguna plataforma Java que haya encontrado.
Una búsqueda en Google me encontró un viejo punto de referencia que informa una tasa de creación de subprocesos de ~ 4000 por segundo en un Sun Java 1.4.1 en un procesador dual 2002 Xeon con 2002 Linux vintage. Una plataforma más moderna dará mejores números ... y no puedo comentar sobre la metodología ... pero al menos da una pista sobre cuán costosa es la creación de hilos.
La evaluación comparativa de Peter Lawrey indica que la creación de subprocesos es significativamente más rápida en estos días en términos absolutos, pero no está claro cuánto de esto se debe a mejoras en Java y / o el sistema operativo ... o mayores velocidades de procesador. Pero sus números aún indican una mejora de más de 150 veces si usa un grupo de hilos en lugar de crear / comenzar un nuevo hilo cada vez. (Y él señala que todo esto es relativo ...)
(Lo anterior supone "hilos nativos" en lugar de "hilos verdes", pero las JVM modernas usan hilos nativos por razones de rendimiento. Los hilos verdes son posiblemente más baratos de crear, pero se paga en otras áreas).
He cavado un poco para ver cómo se asigna realmente la pila de un hilo de Java. En el caso de OpenJDK 6 en Linux, la pila de subprocesos se asigna por la llamada pthread_create
que crea el subproceso nativo. (La JVM no pasa pthread_create
una pila preasignada).
Luego, dentro de pthread_create
la pila se asigna mediante una llamada a mmap
lo siguiente:
mmap(0, attr.__stacksize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
Según man mmap
, la MAP_ANONYMOUS
bandera hace que la memoria se inicialice a cero.
Por lo tanto, aunque no sea esencial que las nuevas pilas de subprocesos de Java estén puestas a cero (según la especificación JVM), en la práctica (al menos con OpenJDK 6 en Linux) están puestas a cero.