问题
Finalize method in class ThreadPoolExecutor
Looks like below.
protected void finalize() {
shutdown();
}
Consider below program in which thread never terminates
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(new Runnable() {
@Override
public void run() {
try {
new SynchronousQueue<String>()
.put("will never get removed");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
executorService = null;
System.gc();
}
In such case shutdownNow
would have been better choice than shutdown
at least JVM could have exited in that case.
Update:
Only possible explanation of why finalize
calls shutdown
method is if programmer does not call it explicitly it will get called while GC as a defensive mechanism. I see flaw in this mechanism since in above case JVM will not be terminated.
回答1:
First, let me ask you a question: Why would you need to pool a thread that never terminates? You pool objects to reuse them.
The reason why java calls shutdown, is to give the threads the oportunity to terminate gracefully.
If you need to run a thread in an infinite loop, then your thread should check that Thread.currentThread().isInterrupted()
returs false, and then return from run()
.
In the example you show, you might want to use the method offer()
with a timeout, rather and put()
.
Wost case scenario, you can extend ThreadPoolExecutor
and call shutdownNow()
in the finalizer.
回答2:
The moral of this story is that if you want a ThreadPool to shutdown, you shouldn't be relying on finalize to do it. This is true of any resource in Java, you should never depend on the finalization mechanism (as it may never run). if you want a ThreadPool to shutdown, you should manage it yourself.
The shutdown()
call in the finalize method is a reasonable compromise in the case that a programmer "accidentally" loses track of a ThreadPool. the current tasks will run to completion, and then the pool will shutdown. if shutdownNow()
were used, at some random point in time (depending on the gc), your tasks would get interrupted. probably less than ideal. and, you can always create a task which refuses to shutdown regardless of whether shutdown()
or shutdownNow()
is invoked (just add a while(true)
loop around the try/catch block in your example).
回答3:
When shutdown()
is invoked, it means the pool will not accept new tasks and will actually "shut down" after the submitted tasks have been done. For your case, you'd better invoke shutdownNow()
explicitly somewhere you want.
来源:https://stackoverflow.com/questions/12545279/why-threadpoolexecutor-finalize-invokes-shutdown-and-not-shutdownnow