Скільки потоків може підтримувати Java VM? Чи залежить це від постачальника? операційною системою? інші фактори?
Скільки потоків може підтримувати Java VM? Чи залежить це від постачальника? операційною системою? інші фактори?
Відповіді:
Це залежить від CPU, який ви використовуєте, в ОС, від того, які інші процеси виконуються, від того, який випуск Java ви використовуєте, та інших факторів. Я бачив, як сервер Windows має> 6500 ниток перед тим, як збити машину. Більшість ниток, звичайно, нічого не робили. Після того, як машина потрапила близько 6500 ниток (на Java), у всієї машини почалися проблеми і стали нестабільними.
Мій досвід показує, що Java (останні версії) може із задоволенням споживати стільки ниток, скільки сам комп’ютер може розмістити без проблем.
Звичайно, у вас має бути достатньо оперативної пам’яті, і ви повинні запустити Java з достатньою пам’яттю, щоб зробити все, що нитки роблять, і мати стек для кожної теми. Будь-яка машина із сучасним процесором (останні пару поколінь AMD чи Intel) та 1–2 гіга пам’яті (залежно від ОС) може легко підтримувати JVM з тисячами ниток.
Якщо вам потрібна більш конкретна відповідь, ніж ця, найкраще зробити ваш профіль.
Гм, багато.
Тут є кілька параметрів. Конкретний VM, а також зазвичай є параметри часу роботи на VM. Це дещо керується операційною системою: яку підтримку має основна ОС для потоків і які обмеження вона накладає на них? Якщо VM насправді взагалі використовує нитки рівня ОС, стара хороша червона нитка / зелена нитка.
Що означає "підтримка" - це інше питання. Якщо ви пишете програму Java, яка є щось подібне
class DieLikeADog {
public static void main(String[] argv){
for(;;){
new Thread(new SomeRunaable).start();
}
}
}
(і не нарікайте на маленькі деталі синтаксису, я на своїй першій чашці кави), тоді ви, звичайно, повинні сподіватися, що запустити сотні чи тисячі ниток. Але створення теми є досить дорогим, і накладні витрати планувальника можуть бути інтенсивними; незрозуміло, що ви могли б з цих тем зробити щось корисне.
Гаразд, не втримався. Ось моя маленька тестова програма з парою прикрас:
public class DieLikeADog {
private static Object s = new Object();
private static int count = 0;
public static void main(String[] argv){
for(;;){
new Thread(new Runnable(){
public void run(){
synchronized(s){
count += 1;
System.err.println("New thread #"+count);
}
for(;;){
try {
Thread.sleep(1000);
} catch (Exception e){
System.err.println(e);
}
}
}
}).start();
}
}
}
У ОС / X 10.5.6 на Intel та Java 6 5 (див. Коментарі), ось що я отримав
Нова тема # 2547 Нова тема # 2548 Нова тема # 2549 Неможливо створити потік: 5 Нова тема # 2550 Виняток у потоці "main" java.lang.OutOfMemoryError: не вдається створити нову рідну нитку at java.lang.Thread.start0 (Рідний метод) у java.lang.Thread.start (Thread.javajanju92) на DieLikeADog.main (DieLikeADog.java:6)
Прочитавши публікацію Чарлі Мартіна, мені було цікаво, чи розмір купи має якусь різницю в кількості потоків, які ви можете створити, і я був абсолютно ошелешений результатом.
Використовуючи JDK 1.6.0_11 на Vista Home Premium SP1, я виконав тестову програму Чарлі з різними розмірами купи, від 2 Мб до 1024 МБ.
Наприклад, для створення купи в 2 Мб я б викликав JVM з аргументами -Xms2m -Xmx2m.
Ось мої результати:
2 mb --> 5744 threads
4 mb --> 5743 threads
8 mb --> 5735 threads
12 mb --> 5724 threads
16 mb --> 5712 threads
24 mb --> 5687 threads
32 mb --> 5662 threads
48 mb --> 5610 threads
64 mb --> 5561 threads
96 mb --> 5457 threads
128 mb --> 5357 threads
192 mb --> 5190 threads
256 mb --> 5014 threads
384 mb --> 4606 threads
512 mb --> 4202 threads
768 mb --> 3388 threads
1024 mb --> 2583 threads
Отже, так, розмір купи, безумовно, має значення. Але співвідношення між розміром купи та максимальним числом ниток НЕВЕРЖАЛЬНО пропорційне.
Що дивно.
Я знаю, що це питання досить старе, але просто хочу поділитися своїми висновками.
Мій ноутбук здатний обробляти програму, яка породжує 25,000
потоки, і всі ці потоки записують деякі дані в базу даних MySql через регулярний інтервал 2 секунди.
Я запустив цю програму 10,000 threads
для 30 minutes continuously
тоді і моя система була стабільною , і я був в змозі зробити інші звичайні операції як перегляд, відкриття, закриття інших програм і т.д.
З 25,000 threads
системою, slows down
але вона залишається чуйною.
З 50,000 threads
системою stopped responding
миттєво, і мені довелося перезапустити систему вручну.
Мої деталі системи такі:
Processor : Intel core 2 duo 2.13 GHz
RAM : 4GB
OS : Windows 7 Home Premium
JDK Version : 1.6
Перед запуском я встановив аргумент jvm -Xmx2048m
.
Сподіваюся, це допомагає.
Абсолютний теоретичний максимум , як правило , процес , в адресному просторі користувача ділиться на розмір стека потоку (хоча насправді, якщо вся ваша пам'ять резервується для стеків потоків, ви не будете мати робочу програму ...).
Так, наприклад, у 32-розрядної Windows, де кожен процес має адресний простір користувача 2 Гб, надаючи кожному потоку розмір стека 128 К, ви очікуєте абсолютного максимуму 16384 потоків (= 2 * 1024 * 1024/128). На практиці я вважаю, що я можу запустити близько 13000 під XP.
Тоді, я думаю, ви по суті вирішите, чи (а) ви можете керувати жонглюванням багатьма потоками у своєму коді, а не робити очевидно дурних речей (наприклад, змусити їх усіх чекати на одному об’єкті, а потім викликати notifyAll () ...), та (b) чи може операційна система. В принципі, відповідь на (b) - "так", якщо відповідь на (a) також "так".
Між іншим, ви можете вказати розмір стека в конструкторі Thread ; для цього вам не потрібно (і, мабуть, не варто) возитися з параметрами VM.
Я пригадую, як слухав розмову Clojure, де він мав запустити одне зі своїх додатків на якійсь спеціалізованій машині на виставці з тисячами ядер (9000?), І це завантажило їх усіх. На жаль, зараз я не можу знайти посилання (допомога?).
Виходячи з цього, я думаю, що можна з упевненістю сказати, що обладнання та ваш код є обмежуючими факторами, а не JVM.
Після розігрування з класом DieLikeACode Чарлі, схоже, розмір стека потоку Java є величезною частиною кількості потоків, які ви можете створити.
-Xss встановити розмір стеки Java-нитки
Наприклад
java -Xss100k DieLikeADog
Але у Java є інтерфейс Executor . Я б використав це, ви зможете подати тисячі завдань, що виконується, і Виконавець виконає ці завдання з фіксованою кількістю потоків.
Runnable
/ Callable
насправді потрібно працювати постійно, як, наприклад, коли він має працювати з комунікацією. Але він ідеально підходить для запитів SQL.
Принаймні, для Mac OS X 10.6 32bit є обмеження (2560) операційною системою. Перевірте цю потоку stackoverflow .
Максимальна кількість потоків залежить від наступних речей:
Додаткова інформація про сучасні (systemd) системи Linux.
Є багато ресурсів щодо цього значень, які можуть потребувати налаштування (наприклад, як збільшити максимальну кількість потоків JVM (Linux 64bit) ); однак новий ліміт накладається через системний ліміт "TasksMax", який встановлює pids.max на cgroup.
Для сеансів входу за замовчуванням UserTasksMax становить 33% від обмеження ядра pids_max (зазвичай 12,288) і може бути замінено в /etc/systemd/logind.conf.
Для служб за замовчуванням DefaultTasksMax становить 15% від обмеження ядра pids_max (зазвичай 4 915). Ви можете змінити його для служби, встановивши TasksMax у "systemctl edit" або оновивши DefaultTasksMax в /etc/systemd/system.conf
Ви можете обробити будь-яку кількість потоків; немає межі. Наступний код я запустив під час перегляду фільму та використання NetBeans, і він працював належним чином / без зупинки машини. Я думаю, ви можете зберегти ще більше тем, ніж ця програма.
class A extends Thread {
public void run() {
System.out.println("**************started***************");
for(double i = 0.0; i < 500000000000000000.0; i++) {
System.gc();
System.out.println(Thread.currentThread().getName());
}
System.out.println("************************finished********************************");
}
}
public class Manager {
public static void main(String[] args) {
for(double j = 0.0; j < 50000000000.0; j++) {
A a = new A();
a.start();
}
}
}
main
буде кинутись OutOfMemoryError
, кажучи, що вона більше не може створити нитки. Можливо, @AnilPal ви цього не помічали. Я пропоную включити інший оператор друку у main(..)
метод, щоб чітко побачити, коли він перестає створювати нові теми після викидання помилки.