RejectedExecutionException inside single executor service

前端 未结 1 1660
情书的邮戳
情书的邮戳 2020-12-30 16:16

In one of our services, someone added such (simplified) a piece of code:

public class DeleteMe {

    public static void main(String[] args) {

        Delet         


        
相关标签:
1条回答
  • 2020-12-30 16:59

    You wrote

    To be frank initially I though that ExecutorService is GC-ed - reachability and scope are different things and GC is allowed to clear anything which is not reachable; but there is a Future<?> that will keep a strong reference to that service, so I excluded this.

    But this is actually a very plausible scenario, which is described in JDK-8145304. In the bug report's example the ExecutorService is not held in a local variable, but a local variable does not prevent garbage collection per se.

    Note that the exception message

    Task java.util.concurrent.FutureTask@3148f668 rejected from  
        java.util.concurrent.ThreadPoolExecutor@6e005dc9[Terminated,
            pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
    

    supports this, as the state of ThreadPoolExecutor@6e005dc9 is specified as Terminated.

    The assumption that futures hold a reference to their creating ExecutorService is wrong. The actual type depends on the service implementation, but for the common ones, it will be an instance of FutureTask which has no reference to an ExecutorService. It's also visible in the exception message that this applies to your case.

    Even if it had a reference, the creator would be the actual ThreadPoolExecutor, but it is the wrapping FinalizableDelegatedExecutorService instance which gets garbage collected and calls shutdown() on the ThreadPoolExecutor instance (Thin wrappers are generally good candidates for premature garbage collection in optimized code which just bypasses the wrapping).

    Note that while the bug report is still open, the problem is actually fixed in JDK 11. There, the base class of FinalizableDelegatedExecutorService, the class DelegatedExecutorService has an execute implementation that looks like this:

    public void execute(Runnable command) {
        try {
            e.execute(command);
        } finally { reachabilityFence(this); }
    }
    
    0 讨论(0)
提交回复
热议问题