McGovernTheory 在 Stack Overflow 提了这样一个问题: Java 虚拟机最多支持多少个线程? 跟虚拟机开发商有关么? 跟操作系统呢? 还有其他的因素吗?
其实这取决于你使用的 CPU, 操作系统, 其他进程正在做的事情, 你使用的 Java 的版本, 还有其他的因素. 我曾经见过一台 Windows 服务器在宕机之前有超过 6500 个线程. 当然, 大多数线程什么事情也没有做. 一旦一台机器上有差不多 6500 个线程(Java 里面), 机器就会开始出问题, 并变得不稳定.
以我的经验来看, JVM 容纳的线程与计算机本身性能是正相关的. 当然了, 你要有足够的本机内存, 并且给 Java 分配了足够的内存, 让每个线程都可以拥有栈 (虚拟机栈), 可以做任何想做的事情. 任何一台拥有现代 CPU(AMD 或者是 Intel 最近的几代) 和 1-2G 内存 (取决于操作系统) 的机器很容易就可以支持有上千个线程的 Java 虚拟机.
如果你需要一个更精确的答案, 最好是自己做压测.
这里有很多的参数 (可以设置). 对于特定的虚拟机, 都会有自己的运行时参数.(最大线程数) 一定程度上由操作系统决定的: 底层的操作系统要给线程提供哪些支持? 施加哪些限制? 虚拟机使用的是原生的操作系统的线程还是 red thread 或者 green thread?
操作系统提供的支持是另一个问题. 如果你向下面这样写 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 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)
读了 Charlie Martin 的回复以后, 我很想知道堆内存的大小是否能够给创建的线程数带来不同, 然后我就被结果惊呆了: 在 Vista Home Premium SP1 系统上, 使用 JDK 1.6.0_11, 设置堆内存的大小从 2M 到 1024M 来执行 Charlie 的测试程序. 比如: 创建 2M 的堆内存, 我使用的虚拟机参数是:-Xms2m -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
所以, 堆的大小确实很重要. 但是, 堆大小和最大线程数却是呈反比例关系. 这太诡异了!
绝对理论上的最大线程数是进程的用户地址空间除以线程栈的大小 (现实中, 如果内存全部给线程栈使用, 就不会有能运行的程序了). 因此, 以 32 位 Windows 系统为例, 每一个进程的用户地址空间是 2G, 假如每个线程栈的大小是 128K, 最多会有 16384(=210241024 / 128) 个线程. 实际在 XP 系统上, 我发现大约能启动 13000 个线程.
然后, 我认为, 你的问题本质上是:(a)你是否可以在你的代码中有效的管理许多的线程, 不让他们做很显然是愚蠢的事情 (比如: 让他们在同一个 object 对象上等待随后被调用 notifyAll()...),(b) 操作系统是否可以有效地管理这许多线程. 基本上来说, 如果 (a) 的答案是 "yes" 的话,(b)的答案也是 "yes".
很巧的是, 你可以在 Thread 的构造函数中设置线程栈的大小, 但是, 你不需要也不应该把这个和虚拟机参数弄混淆.
来源: http://www.bubuko.com/infodetail-3097741.html