Створення ниток Java коштує дорого, тому що тут задіяно досить багато роботи:
- Для стека ниток потрібно виділити і ініціалізувати великий блок пам'яті.
- Для створення / реєстрації нативного потоку в хост-операції потрібно здійснити системні виклики.
- Дескриптори повинні бути створені, ініціалізовані та додані до внутрішніх структур даних JVM.
Також дорого в тому сенсі, що нитка зав'язує ресурси, поки вона жива; наприклад, стек потоків, будь-які об'єкти, доступні зі стека, дескриптори потоку JVM, дескриптори натільних потоків ОС.
Витрати на всі ці речі залежать від платформи, але вони недешеві на будь-якій платформі Java, яку я коли-небудь стикався.
Пошук Google знайшов мені старий показник, який повідомляє про швидкість створення потоку ~ 4000 в секунду на Sun Java 1.4.1 на старовинному подвійному процесорі Xeon 2002 під управлінням 2002 vintage Linux. Більш сучасна платформа дасть кращі цифри ... і я не можу коментувати методологію ... але, принаймні, це дає змогу створити дорогу нитку.
Бенчмаркінг Пітера Лорі вказує на те, що створення потоків значно швидше в ці дні в абсолютних показниках, але незрозуміло, наскільки це пояснюється поліпшенням Java та / або ОС ... або більшою швидкістю процесора. Але його цифри все ще вказують на поліпшення в 150 разів, якщо ви використовуєте пул потоків проти створення / запуску нової нитки кожного разу. (І він зазначає, що це все відносно ...)
(Вищенаведене передбачає "рідні потоки", а не "зелені нитки", але сучасні JVM використовують усі основні теми з міркувань продуктивності. Зелені нитки можливо дешевше створити, але ви платите за це в інших областях.)
Я трохи прокопав, щоб побачити, як насправді виділяється стек потоку Java. У випадку OpenJDK 6 в Linux стек потоків розподіляється викликом, pthread_create
який створює нативний потік. (JVM не передає pthread_create
попередньо виділений стек.)
Потім всередині pthread_create
стека виділяється викликом mmap
наступним чином:
mmap(0, attr.__stacksize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
Відповідно man mmap
, MAP_ANONYMOUS
прапор викликає ініціалізацію пам'яті до нуля.
Таким чином, навіть якщо це може бути не суттєво, що нові стеки потоків Java нульові (за специфікацією JVM), на практиці (принаймні, з OpenJDK 6 в Linux) вони нульові.