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

#1 楼

这取决于您正在使用的CPU,操作系统,其他正在执行的操作,您正在使用的Java版本以及其他因素。我已经看到Windows服务器在关闭计算机之前具有> 6500个线程。当然,大多数线程没有执行任何操作。一旦计算机遇到大约6500个线程(使用Java),整个机器就会开始出现问题并变得不稳定。可以毫无问题地进行托管。任何具有现代CPU(最近几代的AMD或Intel)和1-2 Gig内存(取决于OS)的机器都可以轻松地支持具有数千个线程的JVM。

如果需要比这个更具体的答案,最好的办法就是进行简介。

#2 楼

嗯,很多。
这里有几个参数。特定的VM,以及VM上通常也有运行时参数。这在某种程度上是由操作系统驱动的:底层OS对线程有哪些支持?它对线程有什么限制?如果虚拟机实际上完全使用了OS级别的线程,那么旧的红色线程/绿色线程就可以了。
“支持”的含义是另一个问题。如果您编写的Java程序类似于
   class DieLikeADog {
         public static void main(String[] argv){
             for(;;){
                new Thread(new SomeRunaable).start();
             }
         }
    }

(并且不抱怨语法的细节问题,那我就是第一杯咖啡),那么您当然应该期望获得数百或成千上万的线程正在运行。但是创建一个线程是相对昂贵的,并且调度程序的开销会变得非常大。尚不清楚您可以让这些线程做任何有用的事情。
更新
好吧,无法抗拒。这是我的小测试程序,带有一些修饰词: />

评论


您以多少内存启动了JVM?那很重要。

–艾迪
09年4月18日在15:53

Java 6更新13,Ubuntu 8.10 32位,4G内存,默认JVM设置= 6318线程。

– Steve K
09年4月18日在17:32

呵呵,玩线程堆栈大小。 java -Xss100k允许我在Linux中创建19702个线程。

– Steve K
09年4月18日在17:40

java -Xss50k让我大约有32k个线程。那虽然使我的4兆公羊最大。我不得不停止一些正在运行的进程,以在我的机器上获得足够的内存,以便派生一个新进程来杀死Java;)-好时机。

– Steve K
09年4月18日在17:46

在Windows 7上使用Java 7之前,我刚刚创建了200,000个线程,然后系统死了。任务管理器显示了使用8GB RAM的过程。不知道为什么它停在那里,但是...我的计算机上有12GB的RAM。因此,这可能会达到其他极限。

– Dobes Vandermeer
2012年3月26日上午10:35

#3 楼

在阅读了Charlie Martin的文章之后,我很好奇堆大小是否会影响您可以创建的线程数,结果让我感到非常震惊。

在Vista上使用JDK 1.6.0_11在Home Premium SP1中,我以2 MB到1024 MB之间的不同堆大小执行了Charlie的测试应用程序。例如,要创建2 MB堆,我将使用参数-Xms2m调用JVM。 -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


所以,是的,堆大小绝对很重要。但是堆大小和最大线程数之间的关系成反比。

这很奇怪。

评论


如果给每个线程一个该大小的堆,将是有意义的。

–索比昂·拉文·安德森(ThorbjørnRavn Andersen)
09年4月18日在18:56

注意:我的机器没有2583 GB的RAM。或交换。而且JVM不会分配线程本地堆空间。所以不可能...

– Benjismith
09年4月18日在20:37

堆大小会减少可用于堆栈的地址空间。 256K /堆栈的地址空间很有意义。

– Tom Hawtin-大头钉
09年4月20日在12:00

是的,这表明了同样的事情pequenoperro.blogspot.com/2009/02/less-is-more.html

–托比
2010-12-10 16:43

#4 楼

我知道这个问题已经很老了,但只想分享我的发现。

我的笔记本电脑能够处理产生25,000线程的程序,所有这些线程均以2秒的固定间隔在MySql数据库中写入一些数据。

我用10,000 threads30 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

希望对您有所帮助。

评论


“慢下来”听起来像交换。

–索比昂·拉文·安德森(ThorbjørnRavn Andersen)
2014年3月30日15:30

谢谢。这是一台非常坚固的机器,可以工作近8年,直到突然停止启动。我只是在其上而不是Windows上安装了Ubuntu,它又开始处理数字:)

– Shekhar
18/12/19在16:08

炸核心2二重奏与Ubuntu调味料:D

– Pasupathi Rajamanickam
19年7月9日在20:23

我在生产环境中遇到了类似的问题,我的一位同事忘记了关闭线程池,因此每次执行该代码都会导致线程数量增加。结果,响应速度非常慢,起初我们知道cpu的使用率很高,并且我们知道“ vm线程”是使用率最高的1个CPU。在jstack之后,我们检查了jvm内存监视器,但是没有什么特别的。最后,在calalina.log中,我们发现了一些异常,关于“线程无法回收”的错误太多。我花了很多时间在上面,我想要一种方法。

–杰克
9月25日0:21

#5 楼

绝对的理论最大值通常是进程的用户地址空间除以线程堆栈大小(尽管实际上,如果所有内存都为线程堆栈保留,则您将没有可用的程序...)。

因此,例如在32位Windows下,每个进程的用户地址空间为2GB,每个线程的堆栈大小为128K,则您期望绝对最大为16384个线程(= 2 * 1024 * 1024 / 128)。在实践中,我发现我可以在XP下启动约13,000个计算机。事情(例如让它们全部在同一个对象上等待,然后调用notifyAll()...),以及(b)操作系统是否可以。原则上,如果(a)的答案也为“是”,则(b)的答案为“是”。

顺便说一下,可以在Thread的构造函数中指定堆栈大小;为此,您不必(也可能不应)弄乱VM参数。

评论


因此,请使用64位操作系统。我们大家现在使用64位处理器多长时间了?

– Tom Hawtin-大头钉
09年4月20日在12:01

当然,我仅举一个理论上与实践上的极限的例子。请注意,仍然有很多32位计算机(包括服务器)...

–尼尔·科菲(Neil Coffey)
09年4月20日在12:19

#6 楼

在玩完Charlie的DieLikeACode类之后,看起来Java线程堆栈大小是可以创建的线程数量的很大一部分。


-Xss设置java线程堆栈大小


例如


java -Xss100k DieLikeADog


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

评论


我们可以命名为DieLikeACat吗?除非您运行它,否则它不会死也不会死。

–好酒
13年8月14日在21:38

感谢您指出执行器,人们应该更频繁地使用它。但是,如果Runnable / Callable实际上需要连续运行(例如它必须处理通讯时),它将无法正常工作。但这是SQL查询的完美选择。

–马修
14-10-24在8:28

#7 楼

我回想起Clojure的一次演讲,他在一次贸易展览会上必须在一台专用计算机上运行他的应用程序,其中包含数千个内核(9000?),并且全部加载了。不幸的是,我现在找不到链接(帮助?)。

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

评论


你能再看一次吗?我希望看到它-听起来很有趣,并支持功能语言易于跨内核扩展。

–索比昂·拉文·安德森(ThorbjørnRavn Andersen)
09年4月18日在18:57

您可以提供一个链接吗?我知道Azul Systems的首席工程师Cliff Click,Jr.在具有864核和768内核的Azul最大的JCA系统(Azul Vega 3系列7300型7380D:AzulSystems.Com/products/compute_appliance_specs.htm)上运行了Rich Hickey的蚁群模拟GB RAM和700颗蚂蚁设法达到700个内核的最大容量。但是9000个内核,这确实令人印象深刻。那是什么机器?

–Jörg W Mittag
09年4月18日在22:10

我相信这是“ Ants”模拟-这是Rich Hickey(Clojure的创建者)谈论此问题的链接-blip.tv/clojure/clojure-concurrency-819147。它是在具有800多个内核的大型Azul系统箱上进行的,主要用来演示Clojure在处理多核并发方面的表现如何。

– mikera
2011年7月18日在19:50

@mikera lins已过期。

–索比昂·拉文·安德森(ThorbjørnRavn Andersen)
2014年3月30日15:32

#8 楼

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

#9 楼

最大线程数取决于以下因素:

硬件配置(例如微处理器,RAM)。
操作系统(例如32位或64位)
run方法中的代码。如果run方法中的代码巨大,则单线程对象将有更多的内存需求

#10 楼

有关现代(系统化)Linux系统的附加信息。

有许多关于此值的资源可能需要调整(例如,如何增加JVM线程的最大数量(Linux 64位))。但是,通过systemd“ TasksMax”限制强加了一个新限制,该限制在cgroup上设置了pids.max。并且可以在/etc/systemd/logind.conf中覆盖。对于服务,DefaultTasksMax默认值为内核限制pids_max的15%(通常为4,915)。您可以通过在“ systemctl edit”中设置TasksMax来覆盖该服务,或在/etc/systemd/system.conf
中更新DefaultTasksMax。

#11 楼

2017年...
DieLikeADog类。

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

i7-7700
16GB内存

评论


场外答案会有所不同。我得到10278和6 GB的RAM。

–杰米
17年11月26日在19:02

#12 楼

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


评论


我知道这是评论的后期,但是我相信您能够启动并运行许多线程的原因是(假设正常且合理的系统配置)每个线程基本上从输出中打印出一行,然后没有更多理由存在并很快被杀死,从而确保资源的连续可用性。

–ucsunil
2014年10月13日在8:10

@ucsunil这不是真的。我认为您误读了代码。我只是尝试过,不同的线程不仅打印出第一行,而且打印出了它们的名称。这意味着它们是活动的。如果您认为垃圾回收会回收未引用的线程,则不会,请参见此处。

– Evgeni Sergeev
16-2-26在15:04

但是,不久之后,main将在我的机器上抛出一个OutOfMemoryError,表示它无法再创建任何线程。也许@AnilPal,您没有注意到。我建议在main(..)方法中包含另一个print语句,以清楚地看到引发错误后何时停止创建新线程。

– Evgeni Sergeev
16-2-26在15:06

令人惊叹的...真正的图灵机的发现...无限的资源。

–乔什
16-9-29在14:43