Создание Java-потока стоит дорого, потому что в нем задействовано немало работы:
- Для стека потоков должен быть выделен и инициализирован большой блок памяти.
- Для создания / регистрации собственного потока в хост-системе необходимо выполнить системные вызовы.
- Дескрипторы должны быть созданы, инициализированы и добавлены во внутренние структуры данных JVM.
Это также дорого в том смысле, что поток связывает ресурсы, пока он жив; например стек потоков, любые объекты, доступные из стека, дескрипторы потоков JVM, дескрипторы собственных потоков ОС.
Стоимость всех этих вещей зависит от платформы, но они недешевы для любой платформы Java, с которой я когда-либо сталкивался.
Поиск в Google нашел мне старый эталонный тест , который сообщает о скорости создания потоков ~ 4000 в секунду на Sun Java 1.4.1 на двухпроцессорном Xeon 2002 года выпуска, работающем под управлением винтажного Linux 2002 года. Более современная платформа даст лучшие цифры ... и я не могу комментировать методологию ... но, по крайней мере, она дает приблизительный показатель для , насколько дорогой может быть создание потоков.
Сравнительный анализ Питера Лоури показывает, что создание потоков в наши дни в абсолютном выражении происходит значительно быстрее, но неясно, насколько это связано с улучшениями в 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) они обнуляются.