Answers:
这取决于您正在使用的CPU,操作系统,其他正在执行的操作,您正在使用的Java版本以及其他因素。我已经看到Windows服务器在关闭计算机之前具有> 6500个线程。当然,大多数线程没有执行任何操作。一旦计算机遇到了大约6500个线程(使用Java),整个计算机就会开始出现问题并变得不稳定。
我的经验表明,Java(最新版本)可以愉快地消耗与计算机本身可以承载的尽可能多的线程,而不会出现问题。
当然,您必须具有足够的RAM,并且必须以足够的内存来启动Java,才能完成线程正在执行的所有操作,并为每个线程拥有一个堆栈。任何具有现代CPU(最近几代的AMD或Intel)和1-2 Gig内存(取决于OS)的机器都可以轻松地支持具有数千个线程的JVM 。
如果您需要比此更具体的答案,那么最好的方法是剖析。
嗯,很多。
这里有几个参数。特定的VM,以及VM上通常也有运行时参数。这在某种程度上是由操作系统驱动的:底层OS对线程有什么支持,它对线程有什么限制?如果虚拟机实际上完全使用了OS级别的线程,那就是旧的红色线程/绿色线程。
“支持”是另一个问题。如果您编写的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 / X 10.5.6和Java 6 5(请参见注释)上,这就是我得到的
新线程#2547 新线程#2548 新线程#2549 无法创建线程:5 新线程#2550 线程“主”中的异常java.lang.OutOfMemoryError:无法创建新的本机线程 在java.lang.Thread.start0(本机方法) 在java.lang.Thread.start(Thread.java:592) 在DieLikeADog.main(DieLikeADog.java:6)
在阅读了Charlie Martin的文章之后,我很好奇堆大小是否会影响您可以创建的线程数量,结果令我感到非常震惊。
在Vista Home Premium 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
随后还我的系统是稳定的,我是能够做到像浏览,开放等正常操作,关闭其他程序,等等。
使用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使用固定数量的线程来处理这些任务。
Runnable
/ Callable
实际上需要连续运行(例如它必须处理通讯时),它将无法工作。但这对于SQL查询是完美的。
至少在Mac OS X 10.6 32位上,操作系统有限制(2560)。检查此stackoverflow线程。
有关现代(systemd)linux系统的附加信息。
有许多关于这些值的资源可能需要调整(例如,如何增加JVM线程的最大数量(Linux 64位))。但是,通过systemd“ TasksMax”限制强加了一个新限制,该限制在cgroup上设置了pids.max。
对于登录会话,UserTasksMax缺省值为内核限制pids_max(通常为12,288)的33%,可以在/etc/systemd/logind.conf中进行覆盖。
对于服务,DefaultTasksMax默认值为内核限制pids_max(通常为4,915)的15%。您可以通过在“ 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();
}
}
}
main
将OutOfMemoryError
在我的计算机上抛出一个错误,说它无法创建更多线程。也许@AnilPal,您没有注意到。我建议在该main(..)
方法中包括另一个print语句,以清楚地看到引发错误后何时停止创建新线程。