线程栈是线程的一块私有空间。在 JVM 中可以使用-Xss 参数设置线程栈的大小。
在线程中进行局部变量分配,函数调用时都需要在栈中开辟空间。如果栈的空间分配太小,那么线程在运行时可能没有足够的空间分配局部变量或者达不到足够的函数调用深度,导致程序异常退出;如果栈空间过大,那么开设线程所需的内存成本就会上升,系统所能支持的线程总数就会下降。由于 Java 堆也是向操作系统申请内存空间的,因此,如果堆空间过大,就会导致操作系统可用于线程栈的内存减少,从而间接减少程序所能支持的线程数量。
清单 12 所示代码尝试开设尽可能多的线程,并在线程数量饱和时,打印已经开设的线程数量。
清单 12. 尝试开启尽可能多的线程
public class TestXss {
public static class MyThread extends Thread{
@Override
public void run(){
try {
Thread.sleep( 10000 );
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String[] args){
int count= 0 ;
try {
for ( int i= 0 ;i< 10000 ;i++){
new MyThread().start();
count++;
}
} catch (OutOfMemoryError e){
System.out.println(count);
System.out.println(e.getMessage());
}
}
}
|
清单 13. 配置-Xss1M 时的运行输出
1578
unable to create new native thread
|
一共允许启动 1578 个线程。
清单 14. 配置-Xss20M 时的运行输出
69
unable to create new native thread
|
实验证明如果改变系统的最大堆空间设定,可以发现系统所能支持的线程数量也会相应改变。
Java 堆的分配以 200MB 递增,当栈大小为 1MB 时,最大线程数量以 200 递减。当系统物理内存被堆占据时,就不可以被栈使用。当系统由于内存空间不够而无法创建新的线程时会抛出 OOM 异常。这并不是由于堆内存不够而导致的 OOM,而是因为操作系统内存减去堆内存后剩余的系统内存不足而无法创建新的线程。在这种情况下可以尝试减少堆内存以换取更多的系统空间来解决这个问题。综上所述,如果系统确实需要大量线程并发执行,那么设置一个较小的堆和较小的栈有助于提高系统所能承受的最大线程数。
一级建造师二级建造师消防工程师造价工程师土建职称房地产经纪人公路检测工程师建筑八大员注册建筑师二级造价师监理工程师咨询工程师房地产估价师 城乡规划师结构工程师岩土工程师安全工程师设备监理师环境影响评价土地登记代理公路造价师公路监理师化工工程师暖通工程师给排水工程师计量工程师
执业药师执业医师卫生资格考试卫生高级职称护士资格证初级护师主管护师住院医师临床执业医师临床助理医师中医执业医师中医助理医师中西医医师中西医助理口腔执业医师口腔助理医师公共卫生医师公卫助理医师实践技能内科主治医师外科主治医师中医内科主治儿科主治医师妇产科医师西药士/师中药士/师临床检验技师临床医学理论中医理论