La création de threads Java est coûteuse car il y a pas mal de travail impliqué:
- Un gros bloc de mémoire doit être alloué et initialisé pour la pile de threads.
- Des appels système doivent être effectués pour créer / enregistrer le thread natif avec le système d'exploitation hôte.
- Les descripteurs doivent être créés, initialisés et ajoutés aux structures de données internes à la JVM.
Il est également coûteux en ce sens que le fil attache les ressources tant qu'il est vivant; par exemple, la pile de threads, tous les objets accessibles depuis la pile, les descripteurs de thread JVM, les descripteurs de thread natifs du système d'exploitation.
Les coûts de toutes ces choses sont spécifiques à la plate-forme, mais ils ne sont pas bon marché sur aucune plate-forme Java que je connaisse.
Une recherche sur Google m'a trouvé un ancien benchmark qui rapporte un taux de création de threads d'environ 4000 par seconde sur un Sun Java 1.4.1 sur un Xeon à double processeur vintage 2002 exécutant 2002 vintage Linux. Une plate-forme plus moderne donnera de meilleurs chiffres ... et je ne peux pas commenter la méthodologie ... mais au moins, cela donne une idée du coût probable de la création de threads.
L'analyse comparative de Peter Lawrey indique que la création de threads est beaucoup plus rapide de nos jours en termes absolus, mais on ne sait pas dans quelle mesure cela est dû aux améliorations de Java et / ou du système d'exploitation ... ou à des vitesses de processeur plus élevées. Mais ses chiffres indiquent toujours une amélioration de plus de 150 fois si vous utilisez un pool de threads par rapport à la création / démarrage d'un nouveau thread à chaque fois. (Et il fait remarquer que tout cela est relatif ...)
(Ce qui précède suppose des "threads natifs" plutôt que des "threads verts", mais les JVM modernes utilisent tous des threads natifs pour des raisons de performances. Les threads verts sont peut-être moins chers à créer, mais vous payez pour cela dans d'autres domaines.)
J'ai creusé un peu pour voir comment la pile d'un thread Java est vraiment allouée. Dans le cas d'OpenJDK 6 sous Linux, la pile de threads est allouée par l'appel à pthread_create
qui crée le thread natif. (La JVM ne transmet pas de pthread_create
pile pré-allouée.)
Puis, à l'intérieur pthread_create
la pile est allouée par un appel à mmap
comme suit:
mmap(0, attr.__stacksize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
Selon man mmap
, l' MAP_ANONYMOUS
indicateur provoque l'initialisation de la mémoire à zéro.
Ainsi, même s'il n'est peut-être pas essentiel que les nouvelles piles de threads Java soient mises à zéro (selon la spécification JVM), en pratique (au moins avec OpenJDK 6 sous Linux) elles le sont.