当前位置: 首页 > 知识库问答 >
问题:

线程“main”java.lang.OutofMemoryError中出现异常:无法创建新的本机线程

许自强
2023-03-14
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:717)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:950)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1357)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at com.albertoborsetta.formscanner.api.FormTemplate.findPoints(FormTemplate.java:852)
at com.albertoborsetta.formscanner.model.FormScannerModel.analyzeFiles(FormScannerModel.java:562)
at com.albertoborsetta.formscanner.main.FormScanner.main(FormScanner.java:145)
public void findPoints(BufferedImage image, int threshold, int density,
        int size) throws FormScannerException {
    height = image.getHeight();
    width = image.getWidth();
    int cores = Runtime.getRuntime().availableProcessors();

    ExecutorService threadPool = Executors.newFixedThreadPool(cores - 1);
    HashSet<Future<HashMap<String, FormQuestion>>> fieldDetectorThreads = new HashSet<>();

    HashMap<String, FormQuestion> templateFields = template.getFields();
    ArrayList<String> fieldNames = new ArrayList<>(templateFields.keySet());
    Collections.sort(fieldNames);

    for (String fieldName : fieldNames) {
        Future<HashMap<String, FormQuestion>> future = threadPool.submit(new FieldDetector(threshold, density, size, this, templateFields.get(fieldName), image));
        fieldDetectorThreads.add(future);
    }

    for (Future<HashMap<String, FormQuestion>> thread : fieldDetectorThreads) {
        try {
            HashMap<String, FormQuestion> threadFields = thread.get();
            for (String fieldName : threadFields.keySet()) {
                FormQuestion field = threadFields.get(fieldName);
                fields.put(fieldName, field);
                for (Entry<String, FormPoint> point : field.getPoints().entrySet()) {
                    if (point.getValue() != null) {
                        pointList.add(point.getValue());
                    }
                }
            }
        } catch (InterruptedException | ExecutionException e) {
            throw new FormScannerException(e.getCause());
        }
    }

    threadPool.shutdown();

}

在调用shutdown方法后,这些线程是否会被杀死。我不是java开发人员。我做了一些研发。但我不成功。

共有1个答案

印晋
2023-03-14

问题来自用来保存每个实例以便以后检查它们。

在聊天中,你告诉我你正在检查120.000个文件。这意味着有许多未来创建,当池找到一个插槽时,它将创建一个线程来执行可调用的

因为保存每个实例,所以线程不会被垃圾回收,这就是泄漏的原因。您需要删除所有使用的future,以便GC为下一个线程清除内存。

Iterator<Future<HashMap<String, FormQuestion>>> iterator = fieldDetectorThreads.iterator();
while (iterator.hasNext()) {
    //get the next instance
    Future<HashMap<String, FormQuestion>> thread = iterator.next();
    //Remove it from the set
    iterator.remove();

    //then work on that instance just like before
    try {
        HashMap<String, FormQuestion> threadFields = thread.get();
        for (String fieldName : threadFields.keySet()) {
            FormQuestion field = threadFields.get(fieldName);
            fields.put(fieldName, field);
            for (Entry<String, FormPoint> point : field.getPoints().entrySet()) {
                if (point.getValue() != null) {
                    pointList.add(point.getValue());
                }
            }
        }
    } catch (InterruptedException | ExecutionException e) {
        throw new FormScannerException(e.getCause());
    }
}

但是,如果提交请求的循环花了很长时间才结束(在检查第一个请求之前生成120k未来),那么在发送每个请求之前,这个循环就会中断。

在这种情况下,可能需要将该逻辑拆分为两个线程,一个用于发送请求,一个用于检查结果,直到第一个线程结束并且集合为空。

以防万一,我会在循环之后添加一个关闭请求

threadPool.shutdown();
 类似资料:
  • 它的发生是因为我创建了许多线程,而没有关闭它们?还是经常创造新的? 有人能告诉我在代码中是否做错了什么吗?

  • 问题内容: 我看到这样的评论 我见过这个问题的一个地方是,如果您继续创建线程,而不是直接在线程对象上调用run(),而不是调用start()。这将导致线程对象不被取消引用…因此,一段时间后,出现无法创建新本机线程的消息 在Sun Java论坛上 在我的应用程序中,最初我们计划使用线程,但是后来,我们决定不再需要线程,因此我们只调用run()而不是start()。我们是否需要为新的threadCla

  • 我试图在(1and1VPS)上运行服务器。就在服务器启动和客户机的几个请求(重新加载网页)之后,我得到了这个错误: 但是当我在计算机上运行时,一切都正常。我使用和Centos5.8新安装制作了自己的虚拟服务器,它也在那里工作。 这个内存不足错误的原因可能是什么?如果你有任何建议,请分享。我不知道该怎么处理这个了。

  • 运行5-6小时后,我从spark-driver程序中得到以下错误。我正在使用Ubuntu16.04LTS和Open-JDK-8。 cat/proc/sys/kernel/threads-max “无法创建新的本机线程”显然意味着它与堆无关。所以我相信这更多的是一个操作系统的问题。

  • 我目前正在安装一台新的MongoDB ops manager机器。安装工作正常,但我无法启动mongodb彩信服务。实例0的启动因java而失败。lang.OutOfMemoryError异常。我使用与测试服务器上相同的配置(2个CPU核,8gb ram),在那里服务启动时没有任何中断。更改ulimit配置/使用root用户启动服务无效。 新服务器规格: 2.0Ghz的10个Vcore 48gb内