Java VM支持多少个线程?

Java VM支持多少个线程? 这是否因供应商而异? 通过操作系统? 其他因素?

这取决于您使用的CPU,操作系统,其他进程正在执行的操作,正在使用的Java版本以及其他因素。 我已经看到Windows服务器有> 6500个线程之前,关闭机器。 当然,大部分线程都没有做任何事情。 一旦机器达到6500线程(Java),整个机器开始有问题,变得不稳定。

我的经验表明,Java(最新版本)可以愉快地消耗尽可能多的线程,因为计算机本身可以毫无问题地托管。

当然,你必须有足够的内存,并且必须启动带有足够内存的Java来完成线程正在执行的任务,并为每个线程创建一个堆栈。 任何具有现代CPU的机器(最近几代AMD或英特尔)和1-2G内存(取决于操作系统)都可以轻松支持具有数千个线程的JVM。

如果你需要比这个更具体的答案,你最好的选择是配置文件。

呃,很多。

这里有几个参数。 特定的虚拟机以及虚拟机上通常还有运行时参数。 这在某种程度上是由操作系统驱动的:底层操作系统对线程有什么支持,以及它对它们有什么限制? 如果虚拟机真的使用操作系统级别的线程,好的老红线/绿线程的东西。

什么“支持”的意思是另一个问题。 如果你写一个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(); } } } 

在Intel和OS 6上的OS / X 10.5.6上(见注释),这里是我得到的

新线程#2547
新线程#2548
新线程#2549
无法创建线程:5
新线程#2550
线程“main”中的异常java.lang.OutOfMemoryError:无法创建新的本地线程
        在java.lang.Thread.start0(本地方法)
        在java.lang.Thread.start(Thread.java:592)
        在DieLikeADog.main(DieLikeADog.java:6)

在阅读了查理·马丁的帖子之后,我很好奇堆栈大小是否会影响你创建的线程数量,结果我完全傻眼了。

使用Vista家庭高级版SP1上的JDK 1.6.0_11,我使用不同的堆大小(2 MB和1024 MB之间)执行Charlie的测试应用程序。

例如,要创建一个2 MB的堆,我将使用参数-Xms2m -Xmx2m来调用JVM。

这是我的结果:

 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线程的程序,所有这些线程以2秒的时间间隔在MySql数据库中写入一些数据。

我用10,000 threads 30 minutes continuously运行这个程序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下,每个进程的用户地址空间为2GB,每个线程的堆栈大小为128K,您预计绝对最大值为16384个线程(= 2 * 1024 * 1024/128)。 在实践中,我发现我可以在XP下启动大约13,000个。

然后,我认为你基本上是(a) 可以管理你的代码中的许多线程,而不是做明显愚蠢的事情(比如让他们都等待同一个对象然后调用notifyAll()…)和(b)操作系统是否可以。 原则上,如果答案(a)也是“是”,则对(b)的答案是“是”。

顺便说一句,你可以在Thread的构造函数中指定堆栈的大小 。 你不需要(也可能不应该)混淆VM参数。

我记得听过一个Clojure的演讲,他在一个专门的机器上运行他的一个应用程序,在一个拥有数千个内核(9000?)的交易展会上,并且全部加载了它们。 不幸的是,我现在找不到链接(帮助?)。

基于此,我认为可以肯定地说硬件和代码是限制因素,而不是JVM。

在使用Charlie的DieLikeACode类之后,看起来Java线程的堆栈大小是您可以创建多少个线程的重要组成部分。

-Xss设置java线程堆栈大小

例如

java -Xss100k DieLikeADog

但是,Java有Executor接口。 我将使用它,您将能够提交数千个Runnable任务,并让Executor用固定数量的线程处理这些任务。

如果你问这个问题,你可能想重写你的代码。

2017年… DieLikeADog类。

新线程#92459线程“主”java.lang.OutOfMemoryError异常:无法创建新的本地线程

i7-7700 16GB RAM

至少在Mac OS X 10.6 32位上,操作系统有一个限制(2560)。 检查这个stackoverflow线程 。

最大线程数取决于以下几点:

  • 硬件配置,如微处理器,RAM。
  • 像操作系统是32位还是64位
  • 运行方法内部的代码。 如果run方法内部的代码很大,那么单线程对象会有更多的内存需求
  • 现代(systemd)linux系统的附加信息。

    有很多关于这个值的资源可能需要调整(比如如何增加最大数量的JVM线程(Linux 64位) ); 然而,通过在cgroup上设置pids.max的系统“TasksMax”限制来施加新的限制。

    对于登录会话, UserTasksMax默认为内核限制pids_max的33%(通常为12,288),可以在/etc/systemd/logind.conf中覆盖。

    对于服务, DefaultTasksMax默认值是内核限制pids_max的15%(通常为4,915)。 您可以通过在“systemctl edit”中设置TasksMax或更新/etc/systemd/system.conf中的DefaultTasksMax来覆盖该服务

    您可以处理任意数量的线程; 没有限制。 我在观看电影和使用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(); } } }