【问题标题】:The max number of thread in linuxlinux最大线程数
【发布时间】:2020-11-02 18:11:13
【问题描述】:

我用下面的代码来测试最大线程数,但是很奇怪。

import java.util.concurrent.atomic.AtomicInteger;

public class TestThread extends Thread {
    private static final AtomicInteger count = new AtomicInteger();

    public static void main(String[] args) {
        try{
            while (true) {
                (new TestThread()).start();
            }
        } catch (Error | Exception e) {
            System.out.println(e.getMessage());
        }
    }

    @Override
    public void run() {
        System.out.println(count.incrementAndGet());
        while (true)
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                break;
            }
    }
}

操作系统是ubuntu:18.04,内存是4G,处理器数量是2。 JDK:openjdk1.8.0_252

java -Xss1m -Xms1024m -Xmx1023m TestThread

java -Xss512k -Xms1024m -Xmx1023m TestThread

java -Xss1m -Xms2048m -Xmx2048m TestThread

在结果中,线程数总是等于 10000 左右。

  1. 为什么结果是一样的。
  2. 我在命令中设置了-Xss1m,是不是意味着每个线程只有1m内存? 如果是单独内存的话,第10000个线程就有10G内存,实际上机器只有4G内存。

【问题讨论】:

  • 1.它记录什么错误消息? 2.你有多少总内存(ram+swap)?
  • 错误信息是OOM无法创建新的原生线程。我在 ubuntu 中打印顶部。 KiB Mem:总计 4015860,1923636 免费,1429424 已使用,662800 buff/cache; KiB Swap:总共 1942896 个,1942896 个免费,0 个已使用,2336928 个可用内存
  • ulimit -u 是 15511
  • 这很有趣,有几件事可以限制你可以创建的线程数,但很难说你打的是哪一个。您是否看到生成了 hs_err_pid 日志文件?

标签: java linux jvm


【解决方案1】:

-Xss 确定 Java 线程的最大堆栈大小。当一个线程启动时,操作系统会为这个大小的堆栈创建一个虚拟内存区域,但该内存不会立即分配到物理 RAM 中。

物理页在第一次访问该页的内存时被延迟分配。只要您的线程不调用深层方法,它们就不会使用所有堆栈空间。这就是为什么无论 -Xss 设置什么,在 RAM 中只分配几个底部堆栈页。

Linux 默认启用memory overcommit。这意味着,它允许提交比物理 RAM 量更多的虚拟内存(只要此虚拟内存实际上不是由物理页面支持,就像您的情况一样)。

因此,在您的情况下,OutOfMemoryError 被抛出不是因为堆栈空间,而是由于其他操作系统限制之一:

  • ulimit -u
  • sysctl kernel.pid_max
  • sysctl kernel.threads-max

另见:

【讨论】:

  • 优秀的答案!您提到的最后一个链接(stackoverflow.com/questions/344203/…)还谈到了/proc/sys/vm/max_map_count - 这在内核文档(kernel.org/doc/Documentation/sysctl/vm.txt)中记录为“进程可能拥有的最大内存映射区域数”,但我不确定这是怎么回事对应于进程可以创建的最大线程数-您对此有任何详细信息吗?是否为进程创建的每个线程创建了最少数量的“映射”?
  • @JurajMartinka 通常每个线程堆栈都有两个内存映射:一个用于可访问堆栈区域,另一个用于guard pages。偶然地,可访问的堆栈区域可以与具有相同属性的相邻映射组合(具有 RW 访问的匿名映射),但通常max_map_count 应严格超过预期线程数的 2 倍。
  • 感谢@apangin,需要更多时间查看这些消息。
猜你喜欢
  • 1970-01-01
  • 2011-08-03
  • 2016-03-30
  • 2011-04-20
  • 2016-09-14
  • 2011-10-05
  • 2023-03-03
  • 1970-01-01
相关资源
最近更新 更多