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

前端 未结 2 815
野的像风
野的像风 2021-02-05 15:34

Let\'s assume we have the following code:

List> runningTasks;
ExecutorService executor;
...
void executeTask(Runnable task){
    runningTas         


        
相关标签:
2条回答
  • 2021-02-05 16:13

    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.

    0 讨论(0)
  • 2021-02-05 16:31
    1. Does runningTasks( Future ) hold a reference to the task object? --- Yes
    2. How long does it hold it for? Does it still hold it after the task is complete? --- It holds task reference till the task is complete after that it is removed from queue of ThreadPoolExecutor also in FutureTask.finishCompletion() method we set callable(task) reference to null. FutureTask.finishCompletion() is called inside run and cancel methods of FuturetTask. Thus in run and cancel both cases future doesn't have reference to task.
    3. In order to avoid memtory leaks do I havie to take care to remove the future that was added to the list? --- You are safe if you are using Future.

    If you use ScheduledFuture then you may face memory leak issue as ScheduledFuture.cancel() or Future.cancel() in general does not notify its Executor that it has been cancelled and it stays in the Queue until its time for execution has arrived. It's not a big deal for simple Futures but can be a big problem for ScheduledFutures. It can stay there for seconds, minutes, hours, days, weeks, years or almost indefinitely depending on the delays it has been scheduled with.

    For more details with example of memory leak situation and its solution see my other answer.

    0 讨论(0)
提交回复
热议问题