В руководствах по Java написано, что создание потока стоит дорого. Но почему именно это дорого? Что именно происходит, когда создается поток Java, что делает его создание дорогим? Я принимаю это утверждение как правду, но мне просто интересна механика создания потоков в JVM.
Поток жизненного цикла потока. Создание и удаление потоков не бесплатны. Фактические издержки варьируются в зависимости от платформы, но создание потока требует времени, внося задержку в обработку запроса и требуя некоторой активности обработки JVM и ОС. Если запросы частые и легкие, как в большинстве серверных приложений, создание нового потока для каждого запроса может потребовать значительных вычислительных ресурсов.
От параллельной практики Java на практике
Брайан Гетц, Тим Пайерлс, Джошуа Блох, Джозеф Боубер, Дэвид Холмс, Даг Ли
Печать ISBN-10: 0-321-34960-1
источник
Ответы:
Создание потока Java стоит дорого, потому что в нем задействовано немало работы:
Это также дорого в том смысле, что поток связывает ресурсы, пока он жив; например, стек потоков, любые объекты, достижимые из стека, дескрипторы потоков JVM, дескрипторы собственных потоков ОС.
Стоимость всех этих вещей зависит от платформы, но они недешевы для любой платформы Java, с которой я когда-либо сталкивался.
Поиск Google нашел мне старый тест, который показывает скорость создания потоков ~ 4000 в секунду на Sun Java 1.4.1 на двухпроцессорном старом процессоре 2002 года Xeon под управлением винтажного Linux 2002 года. Более современная платформа даст лучшие цифры ... и я не могу комментировать методологию ... но, по крайней мере, она дает оценку того, насколько дорогостоящим будет создание потоков.
Бенчмаркинг Питера Лоури показывает, что в наши дни создание потоков значительно быстрее в абсолютном выражении, но неясно, насколько это связано с улучшениями в Java и / или ОС ... или более высокими скоростями процессора. Но его числа по- прежнему указывают на 150-кратное улучшение, если вы используете пул потоков вместо создания / запуска нового потока каждый раз. (И он подчеркивает, что это все относительно ...)
(Выше предполагается, что «собственные потоки», а не «зеленые потоки», но все современные JVM используют собственные потоки из соображений производительности. Создание зеленых потоков возможно дешевле, но вы платите за это в других областях.)
Я немного покопался, чтобы увидеть, как действительно выделяется стек потока Java. В случае OpenJDK 6 в Linux стек потоков выделяется вызовом,
pthread_create
который создает собственный поток. (JVM не проходитpthread_create
предварительно выделенный стек.)Затем внутри
pthread_create
стека выделяется вызовmmap
следующим образом:В соответствии с
man mmap
этимMAP_ANONYMOUS
флаг вызывает инициализацию памяти в ноль.Таким образом, даже если может быть необязательно, чтобы новые стеки потоков Java обнулялись (в соответствии со спецификацией JVM), на практике (по крайней мере, с OpenJDK 6 в Linux) они обнуляются.
источник
malloc()
функция C , которую JVM вполне может использовать, не гарантирует, что выделенная память обнуляется (предположительно, чтобы избежать именно таких проблем с производительностью).mmap()
вызова от копирования при записи отображается на нулевой странице, поэтому их initailisation происходит не вmmap()
себе, но когда страницы сначала записываются на, а затем только одна страница в время. То есть, когда поток начинает выполнение, с расходами, созданными потоком, а не потоком-создателем.Другие обсуждали, откуда берутся потоки. Этот ответ объясняет, почему создание потока не так дорого по сравнению со многими операциями, но относительно дорого по сравнению с альтернативами выполнения задач, которые относительно дешевле.
Наиболее очевидная альтернатива выполнению задачи в другом потоке - это запуск задачи в том же потоке. Это трудно понять тем, кто полагает, что большее количество потоков всегда лучше. Логика заключается в том, что если накладные расходы на добавление задачи в другой поток превышают время, которое вы экономите, выполнение задачи в текущем потоке может быть быстрее.
Другой альтернативой является использование пула потоков. Пул потоков может быть более эффективным по двум причинам. 1) повторно использует уже созданные темы. 2) вы можете настроить / контролировать количество потоков, чтобы обеспечить оптимальную производительность.
Следующая программа печатает ....
Это тест для тривиальной задачи, который раскрывает накладные расходы каждой опции потоков. (Эта тестовая задача является той задачей, которая на самом деле лучше всего выполняется в текущем потоке.)
Как видите, создание новой темы стоит всего ~ 70 мкс. Это можно считать тривиальным во многих, если не в большинстве случаев использования. Условно говоря, это дороже, чем альтернативы, и для некоторых ситуаций лучшим решением является пул потоков или вообще не использующий потоки.
источник
Теоретически это зависит от JVM. На практике каждый поток имеет относительно большой объем стековой памяти (я думаю, 256 КБ по умолчанию). Кроме того, потоки реализованы как потоки ОС, поэтому для их создания требуется вызов ОС, то есть переключение контекста.
Поймите, что «дорогой» в вычислительной технике всегда очень относительный. Создание потока очень дорого по сравнению с созданием большинства объектов, но не очень дорого по сравнению со случайным поиском жесткого диска. Вам не нужно избегать создания потоков любой ценой, но создание сотен из них в секунду не является разумным шагом. В большинстве случаев, если ваш дизайн требует большого количества потоков, вы должны использовать пул потоков ограниченного размера.
источник
K
= 1024 иk
= 1000.;) en.wikipedia.org/wiki/KibibyteЕсть два вида потоков:
Правильные потоки : это абстракции вокруг потоковых средств базовой операционной системы. Следовательно, создание потоков обходится так же дорого, как и создание системы - всегда есть издержки.
«Зеленые» потоки : созданные и запланированные JVM, они дешевле, но никакого правильного паралеллизма не происходит. Они ведут себя как потоки, но выполняются в потоке JVM в ОС. Они не часто используются, насколько мне известно.
Самый большой фактор, который я могу вспомнить в накладных расходах на создание потоков, это размер стека, который вы определили для своих потоков. Размер стека потока может быть передан в качестве параметра при работе виртуальной машины.
Помимо этого, создание потоков в основном зависит от ОС и даже от реализации виртуальной машины.
Теперь позвольте мне кое-что отметить: создание потоков стоит дорого, если вы планируете запускать 2000 потоков в секунду, каждую секунду вашего времени выполнения. JVM не предназначена для этого . Если у вас будет пара стабильных рабочих, которых не будут увольнять и убивать снова и снова, расслабьтесь.
источник
Создание
Threads
требует выделения достаточного количества памяти, так как он должен создать не один, а два новых стека (один для кода Java, один для собственного кода). Использование Executors / Thread Pools позволяет избежать накладных расходов, повторно используя потоки для нескольких задач для Executor .источник
Очевидно, суть вопроса в том, что означает «дорогой».
Поток должен создать стек и инициализировать стек на основе метода run.
Для этого необходимо настроить управляющие структуры статуса, т. Е. В каком состоянии он находится в рабочем состоянии, ожидает и т. Д.
Вероятно, есть много синхронизации вокруг настройки этих вещей.
источник