In this code example, the ExecutorService is used one and allowed to go out of scope.
public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(3); executorService.submit(new Runnable() { public void run() { System.out.println("hello"); } }); }
Once executorService is out of scope, it should get collected and finalized. The finalize() method in ThreadPoolExecutor calls shutdown().
/** * Invokes {@code shutdown} when this executor is no longer * referenced and it has no threads. */ protected void finalize() { shutdown(); }
Once shutdown() is called, the pool threads should terminate and the JVM should be allowed to exit. However the executorSerivce is never getting collected and thus the JVM stays alive. Even calls to System.gc() don't seem to work. Why isn't executorService getting collected even after main() terminates?
Note: I know I should call shutdown() myself and I always do outside of testing. I'm curious why finalization isn't working as a back-up here.
The Thread is not garbage collected because there are references to the threads that you cannot see. For example, there are references in the runtime system. When the Thread is created it is added to the current thread group.
No, Garbage collection does not guarantee that a program will not run out of memory. The purpose of garbage collection (GC) is to identify and discard objects that are no longer needed by a Java program, so that their resources can be reclaimed and reused.
A thread pool is a collection of worker threads that efficiently execute asynchronous callbacks on behalf of the application. The thread pool is primarily used to reduce the number of application threads and provide management of the worker threads.
This doesn't really have anything to do with GC being non-deterministic, although it doesn't help! (That is one cause in your example, but even if we 'fixed' it to eat up memory and force a collection, it still wouldn't finalize)
The Worker threads that the executor creates are inner classes that have a reference back to the executor itself. (They need it to be able to see the queue, runstate, etc!) Running threads are not garbage collected, so with each Thread in the pool having that reference, they will keep the executor alive until all threads are dead. If you don't manually do something to stop the threads, they will keep running forever and your JVM will never shut down.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With