当前位置: 首页 > 面试题库 >

创建<100个线程时Java`OutOfMemoryError`

单嘉泽
2023-03-14
问题内容

由于这个错误,我已经阅读,测试并在墙上摔了头一天。

我在名为Listener这样的类中有一些Java代码,如下所示

ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
boolean listening = true;
int count = 0;
while (listening) {
    Runnable worker;
    try {
        worker = new ServerThread(serverSocket.accept()); // this is line 254
        executor.execute(worker);
        count++;
        logger.info("{} threads started", count);
    } catch (Exception e1){
        //...
    }
}

我一直在调整JVM设置-Xmx(从1到15G的-Xss任何地方)和(从104k到512M的任何地方)。服务器具有24
GB的RAM,但还必须运行支持该程序的数据库

创建2-20个线程之后(程序中其他地方也有几十个线程),我得到了错误

Exception in thread "Thread-0" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:657)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:943)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1325)
at xxx.Listener.run(Listener.java:254)

$java -version 产量:

java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.1) (fedora-65.1.11.1.fc16-x86_64)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)

发生这种情况时,系统上总是有大量的可用内存,其他程序继续可以正常执行。是什么导致Java认为它没有更多的新线程内存?

更新: 也许这比我想象的要大-当我使用时,我设法得到了这个错误(只有一次)^C

OpenJDK 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGINT to handler- the VM may need to be forcibly terminated

当我尝试杀死客户端时也发生了同样的事情(也是用Java编写的,并且在同一服务器上运行,它是一个读取文件并将其通过套接字发送到服务器的单个线程),因此肯定存在一个限制JVM导致一个干扰另一个,但是我无法想象如果我仍然有可用内存并且根本不使用swap怎么办?服务器-
Xmx1G -Xss104k客户端-Xmx10M

UPDATE2: 放弃perl
Forks::Super库并从bash运行客户端使我可以在服务器因OOME崩溃之前获得多达34个线程,因此运行多个客户端肯定会对服务器产生影响,但同时我仍然应该能够运行一次超过34个Java线程(如果算上客户端,则为68个)。哪些系统资源阻止了更多线程的创建(即,我应该在哪里寻找猪)?当所有内容(客户端,服务器,GC
…)同时用尽内存时,请top说明我的CPU和内存使用情况:

Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  24681040k total,  1029420k used, 23651620k free,    30648k buffers
Swap: 26836988k total,        0k used, 26836988k free,   453620k cached

UPDATE3: 下面的hs_error日志是否表明我的Java不是64位?

# There is insufficient memory for the Java Runtime Environment to continue.
# Cannot create GC thread. Out of system resources.
# Possible reasons:
#   The system is out of physical RAM or swap space
#   In 32 bit mode, the process size limit was hit
# Possible solutions:
#   Reduce memory load on the system
#   Increase physical memory or swap space
#   Check if swap backing store is full
#   Use 64 bit Java on a 64 bit OS
#   Decrease Java heap size (-Xmx/-Xms)
#   Decrease number of Java threads
#   Decrease Java thread stack sizes (-Xss)
#   Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.
#
# JRE version: 6.0_24-b24
# Java VM: OpenJDK 64-Bit Server VM (20.0-b12 mixed mode linux-amd64 compressed oops)
# Derivative: IcedTea6 1.11.1
# Distribution: Fedora release 16 (Verne), package fedora-65.1.11.1.fc16-x86_64

问题答案:

您可以通过来限制max user processes,以了解您的限制用途:

ulimit -u

更改限制:

/etc/security/limits.conf集:

user soft nproc [your_val] 
user hard nproc [your_val]

如果还不够,您可能需要添加一些其他配置,请参阅此链接。

注意:OP
在fedora和centos中发现了此错误报告,解释了编辑的局限性/etc/security/limits.conf



 类似资料:
  • 我正在创建一个可以监视100-150个设备的监视应用程序...现在要设计一个监视器应用程序,我有两种方法: > < li> 为每个要监控的设备创建一个线程,每个线程将ping(使用ICMP)设备以了解设备是否在线。这些线程将无限期地运行,以便在特定的时间间隔(比如60秒)后了解它们的状态。 创建一个线程池,并为每个设备提交一个任务到一个线程池。任务是简单地 ping 到设备。因此,在当前设计中,任

  • 问题内容: 我是线程新手。我想创建一些与主线程分开工作的简单函数。但这似乎不起作用。我只想创建一个新线程,并在那里独立于主线程发生的事情做一些事情。这段代码看起来很怪异,但到目前为止,我对线程的了解还很少。你能解释一下这是怎么回事吗? 问题答案: 您正在线程方法中调用该方法。但是只有在线程已经启动时才调用该方法。改为这样做:

  • 本文向大家介绍java 线程创建多线程详解,包括了java 线程创建多线程详解的使用技巧和注意事项,需要的朋友参考一下 Java 线程类也是一个 object 类,它的实例都继承自 java.lang.Thread 或其子类。 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: Tread thread = new Thread(); thread.sta

  • 问题内容: 传统观点告诉我们,大量的企业Java应用程序应优先使用线程池,而不是产生新的工作线程。使用使得这很简单。 但是,确实存在线程池不太适合的情况。我当前正在使用的具体示例是使用,它允许将变量“传递”给任何产生的线程。使用线程池时,此机制会中断,因为辅助线程通常不是从请求线程派生的,而是预先存在的。 现在有解决方法(可以将线程局部变量显式传入),但这并不总是适当或实际的。最简单的解决方案是按

  • 问题 你创建一个工作者线程池,用来响应客户端请求或执行其他的工作。 解决方案 concurrent.futures 函数库有一个 ThreadPoolExecutor 类可以被用来完成这个任务。 下面是一个简单的TCP服务器,使用了一个线程池来响应客户端: from socket import AF_INET, SOCK_STREAM, socket from concurrent.futures

  • 问题内容: 我是Java技术的新手。我知道在Java中只有两种创建方式 扩展线程类 实施可运行接口 因此,这只是两种创建方法。但是,当我们使用主JVM启动程序时,它启动了一个main 。我认为甚至JVM也必须遵循创建主要方法的规则,以创建主线程JVM必须扩展Thread类或实现。 我尽了最大的努力,但是不知道JVM是如何创建这个主要对象的。当我完全遍历主类()时,我知道这是负责主线程的类。但是在G