zoukankan      html  css  js  c++  java
  • linux服务器上增加线程数量的两种思路

    工作中碰到Java程序报错,无法创建本地线程。在这里总结一下。

    思路1, 通过ulimit指令限制 shell 多线程程序堆栈的大小,达到增加可用线程数量的目的

    个例子取自于一个真实的案例。我们所遇到的问题是系统对我们的多线程程序有如下的限制:

    ulimit -v 200000

    根据本文前面的介绍,这意味着我们的程序最多只能使用不到 200MB 的虚拟内存。由于我们的程序是一个多线程程序,程序在运行时会根据需要创建新的线程,这势必会增加总的内存需求量。一开始我们对堆栈大小的限制是 1024 (本例子中使用 1232 来说明):

     # ulimit – s 1232
    

     

    当我们的程序启动后,通过 pmap 来查看其内存使用情况,可以看到多个占用 1232KB 的数据段,这些就是程序所创建的线程所使用的堆栈:

    每当一个新的线程被创建时都需要新分配一段大小为 1232KB 的内存空间,而我们总的虚拟内存限制是 200MB,所以如果我们需要创建更多的线程,那么一个可以改进的方法就是减少每个线程的固定堆栈大小,这可以通过 ulimit – s 来实现:

     # ulimit -s 512 
    

    我们将堆栈大小设置为 512KB,这时再通过 pmap 查看一下我们的设置是否起作用:

    从上面的信息可以看出,我们已经成功的将线程的堆栈大小改为 512KB 了,这样在总内存使用限制不变的情况下,我们可以通过本小节介绍的方法来增加可以创建的线程数,从而达到改善程序的多线程性能。

    思路2,从JVM着手进行

    jvm启动参数之Xss

    -Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M。在sunos下32位java测试这值为512K。可以根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。

    "Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread"异常问题本质原因是程序创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。

    能创建的线程数的具体计算公式如下:
    (MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
    MaxProcessMemory 指的是一个进程的最大内存
    JVMMemory JVM内存
    ReservedOsMemory 保留的操作系统内存
    ThreadStackSize 线程栈的大小

    在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,
    而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。
    由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越容易发生java.lang.OutOfMemoryError: unable to create new native thread。

    --根据测试,这种说法只适用于32位java程序,64位的java不受此限制

    测试程序

    import java.util.concurrent.CountDownLatch;
    
    public class TestNativeOutOfMemoryError {
        public static void main(String[] args) {
            for (int i = 0;; i++) {
                System.out.println("i = " + i);
                new Thread(new HoldThread()).start();
            }
        }
    }
    class HoldThread extends Thread {
        CountDownLatch cdl = new CountDownLatch(1);
        public HoldThread() {
            this.setDaemon(true);
        }
        public void run() {
            try {cdl.await();} 
            catch (InterruptedException e) {}
        }
    }

    如果程序确实需要大量的线程,现有的设置不能达到要求,那么可以通过修改MaxProcessMemory,JVMMemory,ThreadStackSize这三个因素,来增加能创建的线程数:

    a, MaxProcessMemory 使用64位JVM

        经测试在,64位jvm下生成的线程数不受上述公式的制约,值为63260,这个数值应该足够用了,

        测试数据如下, (指令|能启动的线程数量)    

    java -Xms512M -Xmx2G -cp . TestNativeOutOfMemoryError   | 63389
    java -Xms512M -Xmx8G -cp . TestNativeOutOfMemoryError   | 63260
    java -Xms512M -Xmx16G -cp . TestNativeOutOfMemoryError  | 63385
    java -Xms512M -Xmx32G -cp . TestNativeOutOfMemoryError  | 63380
    java -Xms512M -Xmx64G -cp . TestNativeOutOfMemoryError  |63387

    b, JVMMemory   减少JVMMemory的分配(即减少xms/xmx的大小)

    c, ThreadStackSize  减小单个线程的栈大小 (-Xss)

  • 相关阅读:
    在Ubuntu-20.04上安装Emacs-27.1
    VSCode 配置 C++ 与 python 编译环境
    cf 1557(div2)
    2021牛客暑期多校训练营8
    2021牛客暑期多校训练营7
    2021暑期cf加训3
    2021牛客暑期多校训练营6
    2021牛客暑期多校训练营5
    3ds Max基本操作
    renren-generator快速生成你搬砖需要的CRUD代码的框架
  • 原文地址:https://www.cnblogs.com/vigarbuaa/p/3118049.html
Copyright © 2011-2022 走看看