Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the future object returned by executorService.submit(Runnable) hold any reference to the runnable object?

Let's assume we have the following code:

List<Future<?>> runningTasks;
ExecutorService executor;
...
void executeTask(Runnable task){
    runningTasks.add(executor.submit(task));
}

My questions are:

  1. Does runningTasks hold a reference to the task object?
  2. How long does it hold it for? Does it still hold it after the task is complete?
  3. In order to avoid memory leaks do I have to take care to remove the future that was added to the list?
like image 479
Daniel Rusev Avatar asked Apr 11 '14 13:04

Daniel Rusev


1 Answers

Until when the executor or the Future object holds a reference to it is an implementation detail. Therefore, if your tasks use a lot of memory such that you have to worry about memory usage, you should explicitly clean up in your task before the task completes.

If you look at OpenJDK 1.6 source code of ThreadPoolExecutor, you can see that in fact the underlying Future object actually retains a reference to the underlying callable object indefinitely (i.e. as long as there is a strong reference to the Future object, the callable cannot be GCd). This is true for 1.7 as well. As of 1.8, the reference to it is nulled out. However, you can't control on which implementation of ExecutorService your task will run.

Using a WeakReference should work in practice as the Future and thus the Callable object can be GCd once the task is done and sane implementations of ExecutorService should lose reference to it when the task is done. Strictly speaking this still depends on the implementation of the ExecutorService though. Moreover, use of WeakReference can add surprisingly large overhead. You are much better off simply explicitly cleaning up whatever object that's taking up a lot of memory. Conversely, if you aren't allocating large objects then I wouldn't worry.

Of course this discussion is entirely different from the memory leak you'll have if you keep adding futures to your list without ever removing any. If you do this even using WeakReference wouldn't help; you'll still have a memory leak. For this, simply iterate through the list and remove futures that are already done and thus are of no use. It's really fine to do this every time unless you have a ridiculously large queue size as this is very quick.

like image 95
Enno Shioji Avatar answered Oct 13 '22 17:10

Enno Shioji