当我增加最大堆大小时,为什么最大线程数会减少?

Evg*_*eev 17 java memory heap multithreading

此测试显示可以在Java中创建的最大线程数

    System.out.println("Max memory  " + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "M");
    for (int i = 0;; i++) {
        Thread t = new Thread() {
            public void run() {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                }
            };
        };
        try {
            t.start();
        } catch (Error e) {
            System.out.println("Max threads " + i);
            e.printStackTrace();
            System.exit(1);
        }
    }
Run Code Online (Sandbox Code Playgroud)

当我使用默认堆大小(256M)运行它时,我得到了

Max memory  247M
Max threads 2247
java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:691)
    at test.Test1.main(Test1.java:19)
Run Code Online (Sandbox Code Playgroud)

当我将最大堆大小增加到512M时,我得到了

Max memory  494M
Max threads 1906
...
Run Code Online (Sandbox Code Playgroud)

当我将最大堆大小增加到1024M时,我得到了

Max memory  989M
Max threads 1162
...
Run Code Online (Sandbox Code Playgroud)

也就是说,更多的堆内存更少的线程.这是为什么?

NPE*_*NPE 18

每个线程都需要一个堆栈.分配给堆的内存越多,堆栈的内存就越少.

如果您使用的是32位JVM,这将特别严重,因为该过程将为所有内容(代码,堆,堆栈等)提供不超过4GB的地址空间.我无法在我的64位盒子上重现这种行为,无论我分配给堆的内存多少,"最大线程数"都保持不变.

值得注意的是,许多操作系统使您能够调整堆栈的大小.在Unix上,这是使用完成的ulimit -s.