JVM中的最大线程数?

时间:2011-10-11 13:32:33

标签: java

Java虚拟机可以维护的最大线程数是多少?

我没有在原始问题中解释这一点,但我正在尝试对JVM进行基准测试,并希望尝试查看它可以同时维护多少个线程。

在循环中创建线程直到抛出异常是一个选项,但是,我想知道是否有更好的方法来执行此操作。

7 个答案:

答案 0 :(得分:30)

您的操作系统和硬件配置会受到一些限制。

要提高并发线程数,您应该降低默认的stacksize java -Xss 64k

  • Oracle 32位JVM将为每个线程default to 320kb堆栈大小。
    • 对于具有2gb可寻址内存的32位JVM,这将为您提供最多6.5k个线程。
  • Oracle 64位JVM每个线程的堆栈大小为default to 1M
    • 对于每千兆字节的内存,您将使用默认值获得1024个线程。
  • 仅适用于Linux:
    • ulimit -a将为您提供用户进程和内存的配置限制
    • 您只能在linux cat /proc/sys/kernel/pid_max中获得32k个唯一PID - 最多32k个进程。
    • 您将只获得255k个帖子cat /proc/sys/kernel/threads-max

答案 1 :(得分:9)

编写一个创建新线程的循环,直到它爆炸为止是确定的最终方法。在实际死亡之前,您可能会看到性能严重下降。

我不知道JVM中是否有任何配置参数或其他内置限制。我在练习中从未遇到过限制。当然,迟早你会耗尽内存,也许是其他资源。

我怀疑线程数本​​身没有限制,而是与线程相关的资源。也就是说,你可能会看到你可以拥有10,000个线程,如果它们只运行一个只带有几个字节数据的小类,但当它们各自拥有1000万个字符串的数组时,它会快速下降。

答案 2 :(得分:7)

如果有限制,将由操作系统强加,而不是jvm

答案 3 :(得分:1)

真正的问题不应该是你可以创建多少线程,而是有效运行多少线程。太多的线程,你将导致颠簸,太少和更少的计算时间。

首先,问题,你的线程需要多长时间。短线程不值得努力。另一方面,大型计算具有完美的意义。

其次,每个线程消耗多少内存。获取每个线程所需的内存量,并将其除以可用内存量。你不应该创建比这更多的线程。

第三,您有多少CPU可用。您不应该创建比CPU更多的线程。实际上,您应该考虑至少比线程数少一个。在具有4个CPU的Windows笔记本电脑上,如果需要有效处理,则不应超过3个线程。

最后,你的主题是做什么的。如果它读取和写入硬盘驱动器,那么您可以拥有比CPU数量更多的线程,因为它必须等待设备响应。在确定线程数时请考虑以下方法:

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;
}

答案 4 :(得分:0)

最大线程数也可以由JVM实现限制,cab可以与Java虚拟机不同,也可以与另一个Java虚拟机不同。例如,在Jikes RVM中,数组用于保存有关线程的信息(请参阅Jikes RVM Scheduler source code中的第54行)。在这种情况下,最大线程数不能超过Java中数组的最大大小,大约为2 ^ 32。但是,在达到2 ^ 32个线程之前,您更有可能达到其他操作系统限制或硬件限制。

答案 5 :(得分:0)

最大线程限制主要取决于硬件,操作系统和Java堆栈大小。

以下因素在确定最大线程限制方面起着非常重要的作用:-

  1. 处理虚拟地址限制(2^32体系结构为32-bit2^64体系结构为64-bit
  2. Java堆栈大小(可以通过命令java -XX:+PrintFlagsFinal -version | grep -iE 'ThreadStackSize'
  3. 确定
  4. 最大PID限制(可以通过命令“ cat / proc / sys / kernel / pid_max”确定)
  5. 最大进程限制ulimit -u

因此,最大线程限制为MINIMUM(((进程虚拟地址空间/ 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();
 }
}
}

答案 6 :(得分:0)

百万

好吧,如果使用为未来版本的 Java 开发的 Project Loom 技术中的虚拟线程,则数以百万计。

业界更广为人知的名称是 fibers,Loom 项目下的虚拟线程运行在我们在 Java 中已有的“真实”平台/内核线程之上。许多虚拟线程映射到每个平台/内核线程。

虚拟线程提供非常便宜的阻塞。当后台线程上的任务执行文件 i/o、网络调用、数据库访问、日志记录等时,您的代码会阻塞,等待响应。 Project Loom 技术检测到这种阻塞,“停放”(搁置)该虚拟线程,并分配另一个虚拟线程以继续其在平台/内核线程上的工作。这种停车和切换非常快。因此,线程化 Java 应用的性能通常会大幅提升。

因此,主流计算硬件上的 JVM 将能够支持数百万个线程。

注意事项:

  • 虽然虚拟线程使阻塞变得廉价,但这些廉价线程可能正在执行昂贵的工作,例如使用大量内存。因此,在这种情况下,您可能需要对您的任务进行一些限制。
  • 虚拟线程适用于涉及阻塞的代码,这在面向业务的应用中很常见。但是,如果线程工作是CPU-bound,例如处理视频,那么您应该使用数量有限的“真实”平台/内核线程,而不是虚拟线程。

使用虚拟线程就像切换 ExecutorService 的实现一样简单:

ExecutorService executorService = Executors.newVirtualThreadExecutor() ;
…

有关详细信息,请参阅 this 2021-01-15 article。并观看 Ron Pressler 和其他团队成员的几个非常好的视频演示和采访。随着 Loom 的发展,研究更多最新材料。

基于早期访问 Java 17 的 Project Loom 的实验构建是 available now。团队寻求反馈。