在 SingleThreadExecutor 中使用 java.util.concurrent.RejectedExecutionException 的可能原因是什么?

2022-08-31 14:22:38

我在单例中创建了以下执行器:

   final private ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
        final ThreadFactory delegate = Executors.defaultThreadFactory();
        public Thread newThread(Runnable paramAnonymousRunnable) { 
            Thread localThread =      this.delegate.newThread(paramAnonymousRunnable);
            localThread.setName("MyTask-" + localThread.getName());
            localThread.setDaemon(XXX.this.daemonThread);
            return localThread;
        }
    });

在程序执行期间,有很多对单例方法的调用。这些调用在不同的线程中完成,并且可能同时完成。

private void send(final String paramString) {
  try {
      this.executor.execute(new Runnable() {
          public void run() {
              //DO some interesting stuff
          }
      });
  } catch (Exception localException) {
    this.handler.handle(localException);
  }

}

在某些时候,发生了以下堆栈跟踪:

java.util.concurrent.RejectedExecutionException
        at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1774)
        at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:768)
        at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:656)
        at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:589)
        at XXXXX.send(XXXX.java:269)

为什么 JVM 会引发这样的异常?

由 .
线程池没有关闭。singleThreadExecutorLinkedBlockingQueue<Runnable>()

JVM是Oracle JDK 1.6。单例是用Spring创建的,复制自:java.util.concurrent.Executors

   public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
       return new FinalizableDelegatedExecutorService
           (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>(),
                                threadFactory));
   }

答案 1

有两个原因会抛出executeRejectedExecutionException

  1. 队列已满,您无法再添加任何线程
  2. 线程池已关闭

由于您正在使用 ,因此我能看到这种情况发生的唯一方法是因为您关闭了池。LinkedBlockingQueue


答案 2

您可能在调用 后提交了任务。通常停止执行器他们做executor.shutdown()

    executor.shutdown();
    executor.awaitTermination(10, TimeUnit.MINUTES);