Скільки потоків може підтримувати Java VM?


212

Скільки потоків може підтримувати Java VM? Чи залежить це від постачальника? операційною системою? інші фактори?

Відповіді:


170

Це залежить від CPU, який ви використовуєте, в ОС, від того, які інші процеси виконуються, від того, який випуск Java ви використовуєте, та інших факторів. Я бачив, як сервер Windows має> 6500 ниток перед тим, як збити машину. Більшість ниток, звичайно, нічого не робили. Після того, як машина потрапила близько 6500 ниток (на Java), у всієї машини почалися проблеми і стали нестабільними.

Мій досвід показує, що Java (останні версії) може із задоволенням споживати стільки ниток, скільки сам комп’ютер може розмістити без проблем.

Звичайно, у вас має бути достатньо оперативної пам’яті, і ви повинні запустити Java з достатньою пам’яттю, щоб зробити все, що нитки роблять, і мати стек для кожної теми. Будь-яка машина із сучасним процесором (останні пару поколінь AMD чи Intel) та 1–2 гіга пам’яті (залежно від ОС) може легко підтримувати JVM з тисячами ниток.

Якщо вам потрібна більш конкретна відповідь, ніж ця, найкраще зробити ваш профіль.


86

Гм, багато.

Тут є кілька параметрів. Конкретний 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)

10
Скільки пам’яті ви запустили JVM? Це має значення.
— Едді

10
Оновлення Java 6 13, Ubuntu 8.10 32 біт, 4Gig оперативної пам'яті, параметри JVM за замовчуванням = 6318 Теми.
— Стів К

9
Хе, пограйте з розміром стеки ниток. java -Xss100k дозволив мені створити 19702 потоки в Linux.
— Стів K

21
java -Xss50k обернув мене близько 32k ниток. Це максимум моїх 4 балів барана, хоча. Мені довелося зупинити деякі запущені процеси, щоб повернути достатню кількість пам’яті на свою машину, щоб розпалити новий процес для вбивства Java;) - хороші часи.
— Стів К

21
Використовуючи Java 7 у Windows 7, я щойно створив 200 000 ниток до моєї системи. Диспетчер завдань показав процес, використовуючи 8 ГБ оперативної пам’яті. Не впевнений, чому він там зупинився, хоча ... У мене на комп’ютері є 12 Гб оперативної пам’яті. Тож це може бути певною межею.
— Dobes Vandermeer

50

Прочитавши публікацію Чарлі Мартіна, мені було цікаво, чи розмір купи має якусь різницю в кількості потоків, які ви можете створити, і я був абсолютно ошелешений результатом.

Використовуючи 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

Отже, так, розмір купи, безумовно, має значення. Але співвідношення між розміром купи та максимальним числом ниток НЕВЕРЖАЛЬНО пропорційне.

Що дивно.


11
Було б сенс, якби кожній нитці надавали купу такого розміру.
— Thorbjørn Ravn Andersen

1
Caveat: у моєї машини немає 2583 ГБ оперативної пам’яті. Або поміняти місцями. І JVM не виділяє місцевих потоків купи місце. Так що не може бути ...
— benjismith

49
Розмір купи зменшує адресний простір, доступний для стеків. Адресний простір 256K / стек має сенс.
— Том Хотін - тайклін

1
Так, це показує те саме, що pequenoperro.blogspot.com/2009/02/less-is-more.html
— Тобі

39

Я знаю, що це питання досить старе, але просто хочу поділитися своїми висновками.

Мій ноутбук здатний обробляти програму, яка породжує 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.

Сподіваюся, це допомагає.


2
"Уповільнює" звук як обмін.
— Thorbjørn Ravn Andersen

Дякую. Це була досить міцна машина і працювала прекрасно майже 8 років, поки раптом вона не перестала завантажуватися. Я щойно встановив Ubuntu на ньому замість Windows, і він знову почав стискати номери :)
— Shekhar

Дует смаженого ядра 2 з приправою ubuntu: D
— Pasupathi Rajamanickam

31

Абсолютний теоретичний максимум , як правило , процес , в адресному просторі користувача ділиться на розмір стека потоку (хоча насправді, якщо вся ваша пам'ять резервується для стеків потоків, ви не будете мати робочу програму ...).

Так, наприклад, у 32-розрядної Windows, де кожен процес має адресний простір користувача 2 Гб, надаючи кожному потоку розмір стека 128 К, ви очікуєте абсолютного максимуму 16384 потоків (= 2 * 1024 * 1024/128). На практиці я вважаю, що я можу запустити близько 13000 під XP.

Тоді, я думаю, ви по суті вирішите, чи (а) ви можете керувати жонглюванням багатьма потоками у своєму коді, а не робити очевидно дурних речей (наприклад, змусити їх усіх чекати на одному об’єкті, а потім викликати notifyAll () ...), та (b) чи може операційна система. В принципі, відповідь на (b) - "так", якщо відповідь на (a) також "так".

Між іншим, ви можете вказати розмір стека в конструкторі Thread ; для цього вам не потрібно (і, мабуть, не варто) возитися з параметрами VM.


1
Тому використовуйте 64-бітну ОС. Як довго ми всі зараз використовуємо 64-бітні процесори?
— Том Хотін - тайклін

Звичайно, я лише навожу приклад теоретичного та практичного обмеження. Зверніть увагу, там ще дуже багато 32-розрядних машин (включаючи сервери) ...
— Neil Coffey

2

Я пригадую, як слухав розмову Clojure, де він мав запустити одне зі своїх додатків на якійсь спеціалізованій машині на виставці з тисячами ядер (9000?), І це завантажило їх усіх. На жаль, зараз я не можу знайти посилання (допомога?).

Виходячи з цього, я думаю, що можна з упевненістю сказати, що обладнання та ваш код є обмежуючими факторами, а не JVM.


ти міг би знову подивитися? Мені б хотілося це побачити - це звучить цікаво і підтверджує, що функціональні мови легко масштабувати по ядрах.
— Thorbjørn Ravn Andersen

Чи можете ви надати посилання на це? Я знаю, що Кліфф Клік, молодший, провідний інженер компанії Azul Systems, керував моделюванням мурашних колоній Річ Хікі на найбільшій системі JCA Azul (модель 7380D Azul Vega 3 серії 7300D: AzulSystems.Com/products/compute_appliance_specs.htm ) з 864 ядрами і 768 ГБ оперативної пам’яті, а 700 мурашок зуміли максимум 700 ядер. Але 9000 ядер, це досить вражає. Що це за машина?
— Йорг W Міттаг

Я вважаю, що це імітація "Мурашки" - ось посилання, де Річ Хікі (творець Clojure) говорить про це - blip.tv/clojure/clojure-concurrency-819147 . Це було на великій коробці систем Azul з 800+ ядрами, в основному, щоб продемонструвати, наскільки хороший Clojure в обробці багатоядерної одночасності.
— mikera

Термін дії @mikera закінчився.
— Thorbjørn Ravn Andersen

2

Після розігрування з класом DieLikeACode Чарлі, схоже, розмір стека потоку Java є величезною частиною кількості потоків, які ви можете створити.

-Xss встановити розмір стеки Java-нитки

Наприклад

java -Xss100k DieLikeADog

Але у Java є інтерфейс Executor . Я б використав це, ви зможете подати тисячі завдань, що виконується, і Виконавець виконає ці завдання з фіксованою кількістю потоків.


13
Чи можемо ми назвати його DieLikeACat? вона не буде ні мертвою, ні живою, поки не запустите її.
— Goodwine

Дякуємо, що вказували на Виконавців, люди повинні використовувати це частіше. Але це не спрацює, якщо Runnable/ Callableнасправді потрібно працювати постійно, як, наприклад, коли він має працювати з комунікацією. Але він ідеально підходить для запитів SQL.
— Матьє


0

Максимальна кількість потоків залежить від наступних речей:

  • Конфігурація обладнання, наприклад мікропроцесор, оперативна пам'ять.
  • Операційна система, як-от 32-розрядна чи 64-розрядна
  • Код всередині методу запуску. Якщо код у методі запуску величезний, то для одного об’єкта буде потрібна більше пам'яті

  • 0

    Додаткова інформація про сучасні (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


    0

    Рік 2017 ... клас DieLikeADog.

    Нова тема # 92459 Виняток у потоці "main" java.lang.OutOfMemoryError: не вдається створити нову рідну нитку

    i7-7700 16 Гб оперативної пам’яті


    Відбійні відповіді будуть різними. Я отримав 10278 з 6 ГБ оперативної пам’яті.
    — jamie

    -4

    Ви можете обробити будь-яку кількість потоків; немає межі. Наступний код я запустив під час перегляду фільму та використання 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();
            }
        }
    }

    7
    Я знаю, що це зауваження дуже пізно, але я вважаю, що причина, коли вам вдалося запустити та запустити ці багато потоків, полягає в тому, що (за умови нормальної та розумної конфігурації системи) кожен потік в основному виводить один рядок із виводу, а потім більше немає причин існують і вбиваються незабаром після цього, тим самим забезпечуючи постійну доступність ресурсів.
    — ucsunil

    @ucsunil Це неправда. Я думаю, ви неправильно прочитали код. Я просто спробував це, і різні нитки друкують не лише перший рядок, але й їхні назви. Що означає, що вони активні. Якщо ви думали, що збирання сміття буде переробляти невирішені нитки, це не так, дивіться тут .
    — Євгеній Сергєєв

    1
    Однак через короткий час на мою машину mainбуде кинутись OutOfMemoryError, кажучи, що вона більше не може створити нитки. Можливо, @AnilPal ви цього не помічали. Я пропоную включити інший оператор друку у main(..)метод, щоб чітко побачити, коли він перестає створювати нові теми після викидання помилки.
    — Євгеній Сергєєв

    5
    дивовижне ... відкриття власне машини Тьюрінга ... нескінченних ресурсів.
    — Джош
    Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
    Licensed under cc by-sa 3.0 with attribution required.