Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does an ExecutorService get garbage collected when out of scope?

Tags:

I'm asking this question because I am creating a lot of executor services and while I may already have a memory leak somewhere that needs to be investigated, I think a recent change to the following code actually worsened it, hence I am trying to confirm what is going on:

@FunctionalInterface public interface BaseConsumer extends Consumer<Path> {     @Override     default void accept(final Path path) {         String name = path.getFileName().toString();         ExecutorService service = Executors.newSingleThreadExecutor(runnable -> {             Thread thread = new Thread(runnable, "documentId=" + name);             thread.setDaemon(true);             return thread;         });         Future<?> future = service.submit(() -> {             baseAccept(path);             return null;         });         try {             future.get();         } catch (InterruptedException ex) {             Thread.currentThread().interrupt();         } catch (ExecutionException ex) {             throw new RuntimeException(ex);         }     }      void baseAccept(final Path path) throws Exception; } 

Then this Consumer<Path> gets called on another thread pool with (usually) N=2 threads, I am not sure if that is relevant.

The question is: Does the ExecutorService service go out of scope and get garbage collected once BaseConsumer#accept has finished?

like image 788
skiwi Avatar asked Jul 25 '14 10:07

skiwi


People also ask

Do you need to shutdown down ExecutorService?

An unused ExecutorService should be shut down to allow reclamation of its resources.

What is ExecutorService and how its works?

ExecutorService is a JDK API that simplifies running tasks in asynchronous mode. Generally speaking, ExecutorService automatically provides a pool of threads and an API for assigning tasks to it.

How do you ensure that an instance is not garbage collected?

We have three ways to achieve same - 1) Increasing the Heap -Eden space size . 2) Create Singleton class with Static reference . 3) Override finalize() method and never let that object dereference.

Does Java do garbage collection automatically?

Java garbage collection is an automatic process. The programmer does not need to explicitly mark objects to be deleted. The garbage collection implementation lives in the JVM.


1 Answers

Does the ExecutorService service go out of scope and get garbage collected once BaseConsumer.accept() has finished?

Yes.

Indeed, the associated thread pool should also be garbage collected ... eventually.

The ExecutorService that is created by Executors.newSingleThreadExecutor() an instance of FinalizableDelegatedExecutorService. That class has finalize() method that calls shutdown() on the wrapped ExecutorService object. Provided that all outstanding tasks actually terminate, the service object will shut down its thread pool.

(AFAIK, this is not specified. But it is what is implemented according to the source code, in Java 6 onwards.)


Does adding a finally { service.shutdown(); } in the try-catch around future.get() help in retrieving resources quicker? (not necessarily garbage collecting the service object).

Yes it does. Calling shutdown() causes the threads to be released as soon as the outstanding tasks complete. That procedure starts immediately, whereas if you just left it to the garbage collector it wouldn't start until the finalizer was called.

Now if the resources were just "ordinary" Java objects, this wouldn't matter. But in this case, the resource that you are reclaiming is a Java thread, and that has associate operating system resources (e.g. a native thread), and a non-trivial chunk of out-of-heap memory. So it is maybe worthwhile to do this.

But if you are looking to optimize this, maybe you should be creating a long-lived ExecutorService object, and sharing it across multiple "consumer" instances.

like image 111
Stephen C Avatar answered Sep 21 '22 19:09

Stephen C