Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manage memory when using ExecutorService?

I have a large mount of tasks need to execute with multithreading.

I use the ExecutorService to submit lots of Callable objects, and each Callable object contains some resource which is needed for executing.

Problem

These tasks are so many that the Callable objects submitted to ExecutorService occupy too much memory then the heap is exhausted.

I want to know, when does the JVM release the space for these Callable objects?

Does it do this immediately after the task is done and how could I to manage the memory used for ExecutorService?

I want to control the submission to ExecutorService, for example, when the memory is not enough then block the submission util some tasks completed and free space. Could it?


The whole code is too compliticated, I will attach the main frame of my code.

public class MyCallable implements Callable<Result> {

  ... // Some members

  public MyCallable(...) {
    ...
  }

  @Override
  public Result call() throws Exception {
    ... // Doing the task
  }
}

class MyFutureTask extends FutureTask<Result> {

  ... // Some members

  public MyFutureTask(...) {
    super(new MyCallable(...));
  }

  @Override
  public void done() {
    Result result = get();
    ... // Something to do immediately after the task is done
  }
}

// Here is the code to add tasks
ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize);
while (...) {
  ... // Reading some data from files
  executor.submit(new MatchFutureTask(...));
}
executor.shutdown();
like image 242
Auguste Avatar asked Mar 01 '12 04:03

Auguste


2 Answers

If you're using the ExecutorService, you must be passing a BlockingQueue into the constructor, right? I am assuming you are using a ThreadPoolExecutor. Use an ArrayBlockingQueue with a fixed capacity, and pass ThreadPoolExecutor.CallerRunsPolicy to the ThreadPoolExecutor constructor. This will fairly effectively limit your submission rate if you set the maximumPoolSize to some reasonable value.

To answer your first question, the VM will release the memory "at some time after" there are no longer any references to objects. If the Callable is self-contained in terms of state, once it is finished executing, the VM should garbage collect it before giving you an out of memory error.

like image 74
brettw Avatar answered Oct 03 '22 08:10

brettw


The method Runtime.getRuntime().freeMemory() will tell you how much free memory the JVM has. You could write a ThreadFactory implementation that checks this value before creating a new thread.

like image 20
Dawood ibn Kareem Avatar answered Oct 03 '22 06:10

Dawood ibn Kareem