`
jackyhongvip
  • 浏览: 154743 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

单个进程最大线程数

    博客分类:
  • j2se
阅读更多

原文链接:http://jzhihui.iteye.com/blog/1271122

 

windows 操作系统中允许的最大线程数。

 

===========================================================================

默认情况下,一个线程的栈要预留1M的内存空间

而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程

但是内存当然不可能完全拿来作线程的栈,所以实际数目要比这个值要小。

你也可以通过连接时修改默认栈大小,将其改的比较小,这样就可以多开一些线程。

如将默认栈的大小改成512K,这样理论上最多就可以开4096个线程。

即使物理内存再大,一个进程中可以起的线程总要受到2GB这个内存空间的限制。

比方说你的机器装了64GB物理内存,但每个进程的内存空间还是4GB,其中用户态可用的还是2GB。

如果是同一台机器内的话,能起多少线程也是受内存限制的。每个线程对象都要站用非页面内存,而

非页面内存也是有限的,当非页面内存被耗尽时,也就无法创建线程了。

如果物理内存非常大,同一台机器内可以跑的线程数目的限制值会越来越大。

在Windows下写个程序,一个进程Fork出2000个左右线程就会异常退出了,为什么?

这个问题的产生是因为windows32位系统,一个进程所能使用的最大虚拟内存为2G,而一个线程的

默认线程栈StackSize为1024K(1M),这样当线程数量逼近2000时,2000*1024K=2G(大约),

内存资源就相当于耗尽。

MSDN原文:

“The number of threads a process can create is limited by the available virtual memory.

 By default, every thread has one megabyte of stack space. Therefore, you can create

 at most 2,028 threads. If you reduce the default stack size, you can create more threads. However, your application will have better performance if you create one thread per

processor and build queues of requests for which the application maintains the context

information. A thread would process all requests in a queue before processing requests

in the next queue.”

 

如何突破2000个限制?

可以通过修改CreateThread参数来缩小线程栈StackSize,例如

 

  1. #define MAX_THREADS 50000   
  2.     DWORD WINAPI ThreadProc( LPVOID lpParam ){  
  3.         while(1){  
  4.             Sleep(100000);  
  5.         }  
  6.         return 0;  
  7.     }  
  8.     int main() {  
  9.         DWORD dwThreadId[MAX_THREADS];  
  10.         HANDLE hThread[MAX_THREADS];  
  11.         forint i = 0; i < MAX_THREADS; ++i){  
  12.         hThread[i] = CreateThread(0, 64, ThreadProc, 0, STACK_SIZE_PARAM_IS_A_RESERVATION, &dwThreadId[i]);  
  13.             if(0 == hThread[i]){  
  14.                 DWORD e = GetLastError();  
  15.                 printf(“%d\r\n”,e);  
  16.                 break;  
  17.             }  
  18.         }  
  19.      ThreadProc(0);  
  20.    }  

 

 

服务器端程序设计

如果你的服务器端程序设计成:来一个client连接请求则创建一个线程,那么就会存在2000个限制(在

硬件内存和CPU个数一定的情况下)。建议如下:

The “one thread per client” model is well-known not to scale beyond a dozen clients

or so. If you‘re going to be handling more than that many clients simultaneously,

you should move to a model where instead of dedicating a thread to a client, you

 instead allocate an object. (Someday I’ll muse on the duality between threads and

 objects.) Windows provides I/O completion ports and a thread pool to help you

convert from a thread-based model to a work-item-based model.

1. Serve many clients with each thread, and use nonblocking I/O and level-triggered

readiness notification

2. Serve many clients with each thread, and use nonblocking I/O and readiness

change notification

3. Serve many clients with each server thread, and use asynchronous I/O

--------------------

附:Win32将低区的2GB留给进程使用, 高区的2GB则留给系统使用。

Linux将高位1GB留给内核,低位3GB留给进程

 

linux系统中允许的最大线程数

==========================================================================================

JVM中可生成的最大Thread数量

 

JVM中可以生成的最大数量由JVM的堆内存大小、Thread的Stack内存大小、系统最大

可创建的线程数量(Java线程的实现是基于底层系统的线程机制来实现的,Windows下_beginthreadex,Linux下pthread_create)三个方面影响。


最近想测试下Openfire下的最大并发数,需要开大量线程来模拟客户端。对于一个JVM实例到底能开多少
个线程一直心存疑惑,所以打算实际测试下,简单google了把,找到影响线程数量的因素有下面几个:

-Xms

intial java heap size

-Xmx

maximum java heap size

-Xss

the stack size for each thread

系统限制

系统最大可开线程数

测试程序如下:

  1. import java.util.concurrent.atomic.AtomicInteger;   
  2. public class TestThread extends Thread {   
  3.     private static final AtomicInteger count = new AtomicInteger();   
  4.     public static void main(String[] args) {   
  5.         while (true)   
  6.             (new TestThread()).start();   
  7.     }   
  8.     @Override   
  9.     public void run() {   
  10.         System.out.println(count.incrementAndGet());   
  11.         while (true)   
  12.             try {   
  13.                 Thread.sleep(Integer.MAX_VALUE);   
  14.             } catch (InterruptedException e) {   
  15.                 break;   
  16.             }   
  17.     }   
  18. }   

 

测试环境:

系统:Ubuntu 10.04 Linux Kernel 2.6 (32位)

内存:2G

JDK:1.7

 

测试结果:

◆ 不考虑系统限制

-Xms

-Xmx

-Xss

结果

1024m

1024m

1024k

1737

1024m

1024m

64k

26077

512m

512m

64k

31842

256m

256m

64k

31842

在创建的线程数量达到31842个时,系统中无法创建任何线程。

 

由上面的测试结果可以看出增大堆内存(-Xms,-Xmx)会减少可创建的线程数量,增大线程栈内存

(-Xss,32位系统中此参数值最小为60K)也会减少可创建的线程数量。

 

◆ 结合系统限制

线程数量31842的限制是是由系统可以生成的最大线程数量决定的:/proc/sys/kernel/threads-max,

可其默认值是32080。修改其值为10000:echo 10000 > /proc/sys/kernel/threads-max,

修改后的测试结果如下:

 

-Xms

-Xmx

-Xss

结果

256m

256m

64k

9761

这样的话,是不是意味着可以配置尽量多的线程?再做修改:echo 1000000 > /proc/sys/kernel/threads-max,

 

修改后的测试结果如下:

-Xms

-Xmx

-Xss

结果

256m

256m

64k

32279

128m

128m

64k

32279

发现线程数量在达到32279以后,不再增长。查了一下,32位Linux系统可创建的最大pid数是32678,

这个数值可以通过/proc/sys/kernel/pid_max来做修改(修改方法同threads-max),但是在32系

统下这个值只能改小,无法更大。在threads-max一定的情况下,修改pid_max对应的测试结果如下:

 

pid_max

-Xms

-Xmx

-Xss

结果

1000

128m

128m

64k

582

10000

128m

128m

64k

9507



在Windows上的情况应该类似,不过相比Linux,Windows上可创建的线程数量可能更少。基于线
程模型的服务器总要受限于这个线程数量的限制。

 

总结:

JVM中可以生成的最大数量由JVM的堆内存大小、Thread的Stack内存大小、系统最大可创建的线程数量

(Java线程的实现是基于底层系统的线程机制来实现的,Windows下_beginthreadex,Linux下

pthread_create)三个方面影响。具体数量可以根据Java进程可以访问的最大内存(32位系统上一般2G)、

堆内存、Thread的Stack内存来估算。

序:

      在64位Linux系统(CentOS 6, 3G内存)下测试,发现还有一个参数是会限制线程数量:

max user process(可通过ulimit –a查看,默认值1024,通过ulimit –u可以修改此值),

这个值在上面的32位Ubuntu测试环境下并无限制。

将threads-max,pid_max,max user process,这三个参数值都修改成100000,-Xms,

-Xmx尽量小(128m,64m),-Xss尽量小(64位下最小104k,可取值128k)。事先预测在

这样的测试环境下,线程数量就只会受限于测试环境的内存大小(3G),可是实际的测试结果是

线程数量在达到32K(32768,创建的数量最多的时候大概是33000左右)左右时JVM是抛出警告:

Attempt to allocate stack guard pages failed,然后出现OutOfMemoryError无法创建本

地线程。查看内存后发现还有很多空闲,所以应该不是内存容量的原因。Google此警告无果,

暂时不知什么原因,有待进一步研究。

序2:今天无意中发现文章[7],马上试了下,果然这个因素会影响线程创建数量,按文中描述把/proc/sys/vm/max_map_count的数量翻倍,从65536变为131072,创建的线程总数

量达到65000+,电脑基本要卡死(3G内存)… 简单查了下这个参数的作用,在[8]中的描述如下:

“This file contains the maximum number of memory map areas a process may have.

Memory map areas are used as a side-effect of calling malloc, directly by mmap and

 mprotect, and also when loading shared libraries.

While most applications need less than a thousand maps, certain programs,

particularly malloc debuggers, may consume lots of them, e.g., up to one or two

 maps per allocation.

The default value is 65536.”

 

OK,这个问题总算完满解决,最后总结下影响Java线程数量的因素:

Java虚拟机本身:-Xms,-Xmx,-Xss;

系统限制:

/proc/sys/kernel/pid_max,

/proc/sys/kernel/thread-max,

max_user_process(ulimit -u),

/proc/sys/vm/max_map_count。

参考资料:

1. http://blog.krecan.net/2010/04/07/how-many-threads-a-jvm-can-handle/

2. http://www.cyberciti.biz/tips/maximum-number-of-processes-linux-26-kernel-can-handle.html

3. http://geekomatic.ch/2010/11/24/1290630420000.html

4. http://stackoverflow.com/questions/763579/how-many-threads-can-a-java-vm-support

5. http://www.iteye.com/topic/1035818

6. http://hi.baidu.com/hexiong/blog/item/16dc9e518fb10c2542a75b3c.html

7. https://listman.redhat.com/archives/phil-list/2003-August/msg00025.html

8. http://www.linuxinsight.com/proc_sys_vm_max_map_count.html

分享到:
评论
3 楼 寂寞秋江 2014-12-04  
系统,全面,条理清晰,由浅入深,简直是集大成之作。

特别是最后一点,/proc/sys/vm/max_map_count ,这个配置项,以前还没听说过,有收获,多谢多谢。
2 楼 darkjune 2013-05-28  
有点意思, 不错
1 楼 shuhucy 2012-10-22  
实践性很强的实验

相关推荐

    windows 线程ppt

    讲解windows下进程线程概念。进程是不活泼的。若要使进程完成某项操作,它必须至少拥有一个线程,该线程负责执行包含在进程的地址空间中的代码。 实际上,单个进程可能包含若干个线程,所有这些线程都“同时”执行...

    详解Android进程和线程

    写在前面的话 一个Android应用就是一个Linux进程,每个应用在各自...当某个应用组件启动且该应用没有运行其他任何组件时,Android 系统会使用单个执行线程为应用启动新的 Linux 进程。默认情况下,同一应用的所有组件在

    微软操作系统进程管理神器

    微软操作系统进程管理神器,可以更加详细查看系统进程 功能介绍: 显示进程安全令牌(比如安全组列表、特权,以及虚拟化状态)。 加亮显示进程和线程列表中的变化。 列出服务宿主进程中的服务,... 能够杀死单个线程

    多进程服务端和多客户端同时启动

    服务端模拟多进程多线程并发;客户端可以同时开启多个,多线程模拟客户端;代码参考了网上(单个进程单线程服务端,单个客户端单线程)

    C#多线程系列教程PDF文件

    C#多线程学习(一) 多线程的相关概念 ...多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

    多线程面试相关知识点

    多线程则指的是在单个程序中可以同时运行多个不同的线程执行不同的任务. 说明: 线程是程序内的顺序控制流,只能使用分配给程序的资源和环境。 多线程编程的目的,就是"最大限度地利用CPU资源",当某一线程的...

    使用C++获取指定线程的CPU使用率

    简单例子说明如何使用C++实现获取指定线程的CPU使用率

    本项目包括利用多线程、select、poll以及epoll实现的并发处理连接请求

    这两类都要使用到IO多路复用,O多路复用是指单个进程/线程就可以同时处理多个IO请求。有三个方式select、poll、epoll。 select:将文件描述符放入一个集合中,调用select时,将这个集合从用户空间拷贝到内核空间...

    C#线程锁介绍源码

    实际上在web开发中大多数逻辑都是在单个线程中展开的,一个请求都会在一个单独的线程中处理,其中的大部分变量都是属于这个线程的,根本没有必要考虑锁 定,当然对于ASP.NET中的Application对象中的数据,我们就要...

    多线程操作实例源码

    多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。浏览器就是一个很好的多线程的例子,在浏览器中你可以...

    多线程操作实例源码,,

    多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。浏览器就是一个很好的多线程的例子,在浏览器中你可以...

    linux系统编程之线程.zip

    如果任意一个线程调用了exit或_exit,则整个进程的所有线程都终止,由于从main函数return也相当于调用exit,为了防止新创建的线程还没有得到执行就终止,我们在main函数return之前延时1秒,这只是一种权宜之计,即使...

    Java线程详解(线程概念、代码示例、周期解析等)

    内容简介:线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制;但与进程不同的是,同类的多个线程是共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一...

    Java程序设计案例教程-第8章-多线程编程.pptx

    在基于线程的多任务环境中,最小的可调度代码单元是线程,这意味着单个程序可以同时执行两个或更多个任务。例如,文本编辑器可以在打印的同时格式化文本,只要这两个动作是通过两个独立的线程执行即可。 第7页 Java...

    C#的多线程机制探索

    多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。浏览器就是一个很好的多线程的例子,在浏览器中你可以...

    快速入门android AIDL(开启多进程并进行通信)

    二、由于android对单个应用所使用的最大内存做了限制,为了加大一个应用可使用的内存,所以通过多进程来获取多份内存空间。 本篇文章demo重点: 1、开启多进程 2、两个进程之间使用AIDL进行通信

    C#线程入门教程之单线程介绍

    在进程中包括线程,进程可以由一个或多个线程组成。 什么是线程? 线程是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。 什么是多线程? 多线程是指程序中包含多个执行流...

    Java并发编程和多线程的区别

    多线程是在单个程序中创建和管理多个线程,使它们能够并发执行。同时,并发编程更广泛,它包括多线程编程,还包括其他并发技术和编程范式,以解决各种并发问题和场景。 总之,多线程是并发编程的一种具体实现方式,...

    VC学习笔记之四:多线程知识.doc

    多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。浏览器就是一个很好的多线程的例子,在浏览器中你可以...

    Python多线程Threading、子线程与守护线程实例详解

    在单个程序中同时运行多个线程完成不同的工作,称为多线程 对于IO密集型的程序来说,多线程可以利用读IO的时间去做其他事【IO并不占用CPU,这就好像A买个一份外卖,他只需要等着送过来然后敲A家的门就行了】; 而...

Global site tag (gtag.js) - Google Analytics