java内存分配不足_java-遗传算法的线程池内存不足-为什么?

本文探讨了一名开发者在使用Java遗传算法进行并行化时遇到的内存溢出问题,特别是在随着种群规模增加时。作者尝试了多种方法如固定线程池、垃圾回收,但问题依旧。文章着重于分析可能的原因,包括线程池管理、内存泄漏和系统资源限制,并提供了可能的解决方案和排查思路。
摘要由CSDN通过智能技术生成

因此,我正在努力使遗传算法(用Java编码)并行化,并且我决定使用Executor来管理种群中个体的适应性测试的异步执行.我这样做是因为这意味着我可以创建一个具有固定线程池大小的执行程序,并在每一代中简单地重用那些线程,而不是每一代中都创建新线程.

现在,我已经进行了一系列测试,以随着人口数量的增长监控我的GA的性能,并且遇到了麻烦.执行以下代码:

for(i=1;i<=11; i++){

PopulationSize = 10*i;

for(j=0;j<10;j++){

startTime = System.nanoTime();

P = new Population(PopulationSize, crossOverProbability, mutationProbability, conGens);

while(P.generation()<10){

P.breedNewPop();

}

endTime = System.nanoTime();

time = (endTime - startTime) * Math.pow(10, -9);

System.out.println("Done Trial " + i + ", Round " + j);

}

}

我收到以下错误:

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

让我感到困惑的是,这是在第10轮第4轮试验中发生的-这意味着它能够顺利运行第10轮的前三轮试验.因为运行第4轮时没有什么区别(尤其是第4轮不要求比第10轮的1-3轮更多的线程),所以我不希望它会有任何问题.但是确实如此.

我现在有一个理论,就是Java并没有进行适当的垃圾回收-我的意思是,由于某种原因,Java并没有清除旧的未使用的线程,这就是为什么Java在如此特殊的时刻耗尽了内存.考虑到这就是问题,我尝试在循环内声明和分配P,而不仅仅是分配它.那没有效果.我也尝试添加P = null; System.gc();在循环的最后尝试在创建新的线程池之前强制垃圾回收.同样,这没有什么区别.

以下是与执行程序相关的代码行:

在Population()中:executor = Executors.newFixedThreadPool(popSize);

在Population.findFitness()中:

for(int i=0; i

executor.execute(individuals[i]);

}try {

cdl.await();

} catch (InterruptedException e) {

System.out.println("Error: Thread interrupted.");

}

(我正在使用CountDownLatch等待所有线程的执行完成-从并行化时起我就已经实现了它,方法是将每个Individual的适应性测试放入自己的线程中,而不是通过执行程序使用线程池.该闩锁还似乎比ExecutorService的invokeAll()方法之类的东西更适合我的Personal实现.)

Individual.run()的代码:

public void run(){

try{

findFitness();

}catch (Exception e){

System.out.println("Error in Individual.run(): " + e.getMessage());

}finally{

stopLatch.countDown();

}

}

在这一点上,我对可能导致它的原因不知所措.有谁知道为什么会发生这种情况以及如何解决?

附言我知道我可以尝试运行具有更多内存的JVM,但这仍然不能解释错误的特殊时间.考虑到我正在一台计算机上对该程序进行编程,并最终将其移至另一台计算机上,所以我宁愿了解错误背后的原因,而不是以相对蛮力的方式进行修复.

更新:经过重新运行试验,这次通过JConsole监视线程,我可以确认执行程序正在创建大小合适的线程池.但是,线程池并没有被破坏-每轮测试(即每次通过for循环,计数为j)都会产生一个新的线程池,但是旧的线程池仍然存在.为什么会这样?

解决方法:

创建具有固定大小的线程池的线程时,内存不足似乎是最奇怪的.我怀疑以下情况之一:

>您的线程池实际上不是固定大小的;也就是说,您错误地创建了池.

>您的代码正在其他地方创建线程;例如通过显式调用new Thread().start().这可能会显示在堆栈跟踪中.

另一种可能性是JVM外部的某种原因导致JVM无法分配线程堆栈.这些不在正常的堆内存中分配,因此不会是-Xmx设置.它可能是默认的线程堆栈大小设置,也可能是外部资源限制…或计算机上的常规资源匮乏.

带有此异常消息:

Exception in thread "main" java.lang.OutOfMemoryError:

unable to create new native thread .

这显然不是GC检测到的正常“堆太满”类型的问题.失败的内存分配是对线程堆栈的非堆内存的请求.增大堆大小将无济于事……甚至可能使情况更糟.

强制运行GC也无济于事.即使问题是由分配堆对象触发的,它也无济于事……因为JVM在运行GC之后只会抛出一个堆OOME.

标签:multithreading,memory,threadpool,genetic-algorithm,java

来源: https://codeday.me/bug/20191201/2078963.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值