一个Java虚拟机可以支持多少线程?

一个Java虚拟机可以支持多少线程?这因供应商而异吗?按操作系统?其他因素?

232734 次浏览

嗯,很多。

这里有几个参数。特定的VM,加上VM上通常还有运行时参数。这在某种程度上是由操作系统驱动的:底层操作系统对线程有什么支持,它对线程有什么限制?如果虚拟机实际上使用操作系统级别的线程,那就是红色线程/绿色线程。

“什么,support"手段是另一个问题。如果你写一个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();
}
}
}

在OS/X 10.5.6上的英特尔,和Java 6 5(见评论),这是我得到的

New thread #2547
New thread #2548
New thread #2549
Can't create thread: 5
New thread #2550
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:592)
at DieLikeADog.main(DieLikeADog.java:6)

这取决于您使用的CPU、操作系统、其他进程在做什么、您使用的Java发行版以及其他因素。我曾经见过一台Windows服务器在关闭机器之前有> 6500个线程。当然,大多数线程都没有做任何事情。一旦机器达到大约6500个线程(在Java中),整个机器就开始出现问题,变得不稳定。

我的经验表明,Java(最新版本)可以愉快地使用计算机本身所能承载的尽可能多的线程,而不会出现问题。

当然,你必须有足够的RAM,你必须有足够的内存来启动Java,以完成线程正在做的所有事情,并为每个线程有一个堆栈。任何具有现代CPU(最新的几代AMD或Intel)和1 - 2gig内存(取决于操作系统)的机器都可以轻松支持具有成千上万的人线程的JVM。

如果你需要一个比这更具体的答案,你最好的选择是侧写。

我记得我听过一个关于Clojure的演讲,他在一个贸易展览会上在一些有数千个(9000个?)核的专业机器上运行他的一个应用程序,然后它把它们都加载了。不幸的是,我现在找不到链接(帮助?)

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

在阅读了Charlie Martin的文章后,我很好奇堆大小是否会对您可以创建的线程数量产生影响,结果完全让我目瞪口呆。

使用Vista Home Premium SP1上的JDK 1.6.0_11,我执行Charlie的测试应用程序,使用不同的堆大小,在2mb到1024mb之间。

例如,要创建一个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

堆大小肯定很重要。但是堆大小和最大线程数之间的关系是反比的。

这很奇怪。

在摆弄了Charlie的dielikecode类之后,Java线程堆栈大小似乎是您可以创建的线程数量的很大一部分。

设置java线程堆栈大小

例如

java -Xss100k DieLikeADog

但是,Java有遗嘱执行人接口。我会使用它,你将能够提交数千个可运行的任务,并让Executor处理这些任务与固定数量的线程。

绝对理论最大值通常是进程的用户地址空间除以线程堆栈大小(尽管在现实中,如果你所有的内存都留给线程堆栈,你就不会有一个工作的程序……)

例如,在32位Windows下,每个进程的用户地址空间为2GB,给每个线程128K的堆栈大小,您期望的绝对最大值为16384个线程(=2*1024*1024 / 128)。在实践中,我发现在XP下我可以启动大约13,000。

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

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

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

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

我知道这个问题很老了,但我还是想分享一下我的发现。

我的笔记本电脑能够处理生成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

希望能有所帮助。

最大线程数取决于以下情况:

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

    有很多关于这个值的资源可能需要调整(例如如何增加最大JVM线程数(Linux 64位));然而,一个新的限制是通过systemd“TasksMax”限制来设置pid。Max在cgroup上。

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

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

    < p > 2017年…… DieLikeADog类。< / p >

    新线程#92459 java.lang.OutOfMemoryError:无法创建新的本机线程

    < p > i7 - 7700 16 gb的ram < / p >

    当我在我的2GB三星AMD处理器笔记本电脑上运行Trisquel linux (Ubuntu 18.04)研究这个主题时。它可以管理9534个线程,然后抛出特殊的异常

    at java.base/java.lang.Thread.start0(Native Method)
    at java.base/java.lang.Thread.start(Thread.java:803)
    at Main.main(Main.java:11)
    

    代码:

    public class MultithreadingRunnable implements Runnable {
    public void run() {
    System.out.println("ThreadID " +  Thread.currentThread().getId());
    }
    }
    
    
    
    
    
    
    public class Main {
    public static void main(String[] ars) {
    
    
    for(int i = 0;i<10000;i++){
    Thread mr = new Thread(new MultithreadingRunnable());
    mr.start();
    }
    }
    }