Максимальное количество потоков в JVM?

Какое максимальное количество потоков может поддерживаться виртуальной машиной Java?

Я не объяснил это в своем первоначальном вопросе, но я пытаюсь сравнить JVM и хотел бы попытаться увидеть, сколько потоков он может поддерживать одновременно.

Создание потоков в цикле до тех пор, пока не сгенерировано исключение - это вариант, однако я хотел бы знать, есть ли лучший способ сделать это.

7 ответов

Решение

Написание цикла, который создает новые потоки до тех пор, пока он не взорвется, является окончательным способом выяснить это. Вполне возможно, вы увидите, что производительность ужасно ухудшается, прежде чем она действительно умирает.

Я не знаю, есть ли какой-либо параметр конфигурации или другой встроенный предел в JVM вне моей головы. Я никогда не сталкивался с ограничением на практике. Конечно, рано или поздно вам не хватит памяти, может быть, какой-то другой ресурс.

Я подозреваю, что нет ограничения на количество потоков как таковых, а скорее на ресурсы, связанные с потоком. То есть вы можете увидеть, что у вас может быть 10000 потоков, если все они запускают только один небольшой класс с несколькими байтами данных в каждом, но число быстро уменьшается, когда каждый из них имеет массив из 10 миллионов строк.

Там будут некоторые ограничения, налагаемые вашей операционной системой и конфигурацией оборудования.

Чтобы увеличить количество одновременных потоков, вы должны уменьшить размер стека по умолчанию java -Xss 64k,

  • По умолчанию 32-битная JVM Oracle будет иметь размер стека 320 КБ на поток.
    • Для 32-битной JVM с 2 ГБ адресуемой памяти это даст вам максимум 6,5 тыс. Потоков.
  • 64-битная JVM Oracle по умолчанию будет иметь размер стека на поток.
    • Для каждого гигабайта памяти вы получите 1024 потоков с использованием значений по умолчанию.
  • Только для Linux:
    • ulimit -a предоставит вам настроенные ограничения для пользовательских процессов и памяти
    • Вы получите только 32 000 уникальных PID в Linux. cat /proc/sys/kernel/pid_max - максимум 32 тыс. процессов.
    • Вы получите только 255 тыс. Тем cat /proc/sys/kernel/threads-max

Предел, если он есть, будет установлен операционной системой, а не jvm

Миллионы

Что ж, миллионы, если использовать виртуальные потоки , найденные в технологии Project Loom , разрабатываемой для будущих версий Java.

Более широко известные в отрасли как волокна , виртуальные потоки в Project Loom выполняются поверх «настоящих» потоков платформы/ядра, которые уже есть в Java. Многие виртуальные потоки сопоставляются с каждым потоком платформы/ядра.

Виртуальные потоки обеспечивают очень дешевую блокировку . Когда задача в фоновом потоке выполняет файловый ввод-вывод, сетевые вызовы, доступ к базе данных, ведение журнала и т. д., ваш код блокируется в ожидании ответа. Технология Project Loom обнаруживает эту блокировку, «паркует» (откладывает) этот виртуальный поток и назначает другой виртуальный поток для продолжения работы над потоком платформы/ядра. Эта парковка и переключение происходит очень быстро. В результате многопоточные Java-приложения обычно демонстрируют значительный прирост производительности.

В результате JVM на обычном вычислительном оборудовании сможет поддерживать миллионы потоков.

Предостережения:

  • В то время как виртуальные потоки удешевляют блокировку, эти дешевые потоки могут выполнять дорогостоящую работу, например использовать много памяти. Поэтому в таком случае вам может потребоваться немного ограничить ваши задачи.
  • Виртуальные потоки подходят для кода, включающего блокировку, что часто встречается в бизнес-приложениях. Однако, если многопоточная работа связана с процессором, например, обработка видео, вам следует использовать ограниченное количество «реальных» потоков платформы/ядра, а не виртуальных потоков.

Использовать виртуальные потоки так же просто, как переключить реализацию ExecutorService:

      ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor() ;

Дополнительные сведения см. в этой статье от 15 января 2021 г. . И посмотрите несколько очень хороших видео-презентаций и интервью Рона Пресслера и других членов команды. Изучайте новые материалы по мере развития Loom.

Уже сейчас доступны экспериментальные сборки Project Loom на основе раннего доступа Java 18 . Команда ищет обратную связь.

Реальный вопрос должен заключаться не в том, сколько потоков вы можете создать, а в том, сколько потоков будет работать эффективно. Слишком много потоков, и вы будете вызывать побои, слишком мало и меньше времени вычислений.

Во-первых, вопрос, как долго жить ваша нить. Короткие живые темы вряд ли стоят усилий. Большие вычисления, с другой стороны, имеют смысл.

Во-вторых, сколько памяти будет потреблять каждый поток. Возьмите объем памяти, необходимый каждому потоку, и разделите его на объем доступной памяти. Вы не должны создавать больше тем, чем это.

В-третьих, сколько процессоров у вас есть в наличии. Вы не должны создавать больше потоков, чем процессоры. На самом деле, вы должны учитывать, как минимум, на одно число меньше, чем количество потоков. На ноутбуке с Windows с 4 процессорами у вас никогда не должно быть более 3 потоков, если требуется эффективная обработка.

Наконец, что делает ваша нить. Если он читает и записывает на жесткий диск, то у вас может быть больше потоков, чем число процессоров, так как ему придется ждать ответа устройства. Рассмотрите следующий метод при определении количества потоков:

public static int recommendedThreadCount()
{
    int mRtnValue = 0;
    Runtime runtime = Runtime.getRuntime();
    long maxMemory = runtime.maxMemory();
    long mTotalMemory = runtime.totalMemory();
    long freeMemory = runtime.freeMemory();
    int mAvailableProcessors = runtime.availableProcessors();

    long mTotalFreeMemory = freeMemory + (maxMemory - mTotalMemory);
    mRtnValue = (int)(mTotalFreeMemory/4200000000l);

    int mNoOfThreads = mAvailableProcessors-1;
    if(mNoOfThreads < mRtnValue) mRtnValue = mNoOfThreads;

    return mRtnValue;
}

Максимальный предел потока в основном зависит от аппаратного обеспечения, ОС и размера стека Java.

Следующий фактор играет очень важную роль для определения максимального предела потока:-

  1. Предел обработки виртуального адреса (2^32 за 32-bit архитектура и 2^64 за 64-bit архитектура)
  2. Размер стека Java (может быть определен командой java -XX:+PrintFlagsFinal -version | grep -iE 'ThreadStackSize'
  3. Максимум PID предел (может быть определен командой "cat /proc/sys/kernel/pid_max")
  4. Максимальный лимит процесса ulimit -u

Таким образом, максимальный предел потока будет МИНИМУМ ((обрабатывать виртуальное адресное пространство / размер стека Java), Макс. PID предел, максимальный предел процесса)

например, если максимальный лимит процесса равен 2048 и как минимум из вышеперечисленных минимум является трехфакторным, тогда процесс Java не сможет создать поток, более того.

Чтобы проверить это, можно создать простое Java-приложение, в котором он / она может создать поток в цикле и посмотреть, сколько он может пойти.

Пример:


private static Object lock = new Object();
private static int counter = 0;

public static void main(String[] _args) {
 while (true) {
  new Thread(new Runnable() {
   public void run() {
    synchronized(lock) {
     counter += 1;
     System.err.println("New thread #" + counter);
    }
    while (true) {
     try {
      Thread.sleep(3000);
     } catch (Exception _e) {
      _e.printStackTrace();
     }
    }
   }
  }).start();
 }
}
}

Максимальное количество потоков также может быть ограничено реализацией JVM и может отличаться от виртуальной машины Java к другой виртуальной машине Java. Например, в Jikes RVM массив используется для хранения информации о потоках (см. Строку 54 в исходном коде Jikes RVM Scheduler). В этом случае максимальное количество потоков не может превышать максимальный размер массива в Java, который составляет около 2^32. Но вы, скорее всего, достигнете других пределов ОС или аппаратных ограничений до достижения 2 ^ 32 потоков.

Другие вопросы по тегам