Java ExecutorService堆空间问题

5
我有一个Java多线程问题。我有以下工作类:
public class ThreadWorker implements Runnable {

    //some code in here

    public void run(){
      // invokes some recursion method in the ThreadWorker itself,
      // which will stop eventually
    {
}

使用线程,我正在使用一个ExecutorService:
public static int THREAD_NUMBER = 4;
public static ExecutorServide es = Executors.newFixedThreadPool(THREAD_NUMBER);

在这里添加ThreadWorker类的实例。
public void recursiveMethod(Arraylist<Integers> elements, MyClass data){
     if (elements.size() == 0 && data.qualifies()){
         ThreadWorker tw = new ThreadWorker(data);
         es.execute(tw);
         return;
     }



     for (int i=0; i< elements.size(); i++){
          // some code to prevent my problem
          MyClass data1 = new MyClass(data);
          MyClass data2 = new MyClass(data); 
          ArrayList<Integer> newElements = (ArrayList<Integer>)elements.clone();
          data1.update(elements.get(i));
          data2.update(-1 * elements.get(i));
          newElements.remove(i);
          recursiveMethod(newElements, data1);
          recursiveMethod(newElements, data2);     
     {    
}

问题在于递归树的深度非常大,它的宽度也很大,因此向ExecutorService添加了许多ThreadWorkers,因此在大输入上经过一段时间后会出现问题。
Exception in thread "pool-1-thread-2" java.lang.OutOfMemoryError: Java heap space

这是由于我添加了大量的ThreadWorkersExecutorService以执行,因此导致内存不足。每个ThreadWorker需要大约40 Mb的RAM。
有没有一种方法可以获取已添加到ExecutorService中的线程数(实现runnable接口的类的实例)?这样我就可以在上面显示的代码中(在“//一些代码来防止我的问题”中)添加它。
while ("number of threads in the ExecutorService" > 10){
    Thread.sleep(10000);
}

所以我不会在递归中过深或过广,以避免那些抛出异常的情况。
诚挚地,Sergey Aganezov jr.
2个回答

6
如何创建一个由BlockingQueue支持的ThreadPoolExecutor,并使用ThreadPoolExecutor.CallerRunsPolicy
这样,当没有可用的工作线程来运行任务时,主线程(添加新作业的线程)会自己运行任务,这可以防止添加更多的作业。
有关ThreadPoolExecutor构造函数选项的更多详细信息,请参阅其Javadoc页面。

创建TreadPoolExecutor es = new ThreadPoolExecutor(4, 4, 10000, TimUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));然后将rejectedHandler设置为它 es.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());.在此之后,如果我理解正确,它将处理我的问题,因为一旦运行线程数达到4个并且排队线程数达到10个,下一个添加的任务将被拒绝并在主线程中执行,停止所有其他活动。 - Sergey Aganezov jr

1

我认为你的情况很适合Java JDK中“fork-join”框架。(在Google上搜索该关键字。)

“Fork-Join”可以通过尽可能延迟“切分”来帮助你减少队列中的作业数量。

不过,你必须将你的代码重新构造成这种哲学。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接