单线程执行器发出的RejectedExecutionException异常

5
以下是我的方法,在其中我使用单线程执行器来执行run方法中的一些任务。
  private void trigger(final Packet packet) {

    // this line is throwing exception
    Executors.newSingleThreadExecutor().execute(new Runnable() {
      @Override
      public void run() {
        // some code here
      }
    });
  }

以下是我收到的异常,但我不确定原因是什么?最好的解决方法是什么?
error= java.util.concurrent.RejectedExecutionException: Task com.abc.stuffProc$2@e033da0 rejected from java.util.concurrent.ThreadPoolExecutor@76c2da8f[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
    at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:628)

如果我的trigger方法被多次调用,而它仍在运行之前线程的运行方法,会发生什么?它会启动多个线程还是等待一个线程完成后再启动另一个线程?

是的,那就是完整的代码,我也已经指出了它抛出异常的位置。 - user1950349
你使用的JDK版本是哪个? - Alexandre Dupriez
我正在使用JDK7。 - user1950349
2个回答

1

请看这里: 什么可能导致RejectedExecutionException异常

从错误日志中可以看出,您的ThreadPoolExecutor已经终止。

也许这正是您想要的:

private void trigger(final Packet packet) {

    executor.execute(new Runnable() {
      @Override
      public void run() {
        // some code here
      }
    });
  }

private final ExecutorService executor = Executors.newFixedThreadPool(10);

使用以下步骤重现问题:

public static void main(String[] args) {
    final ExecutorTest et = new ExecutorTest();
    for (int i = 0; i < 50000; i++) {
        et.trigger(i);
    }
    System.out.println("Done");
}

private void trigger(int i) {

    try {
        Executors.newSingleThreadExecutor().execute(() -> {
            try {
                Thread.sleep(1000);
            } catch (final InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        });
    } catch (final Exception e) {
        System.out.println("Test " + i + " with " + Thread.activeCount());
        e.printStackTrace();
    }
}

"Terminated" 的意思是什么?为什么它会被终止? - user1950349
尝试从文档和代码中找出服务何时将被终止。但目前我没有答案。还尝试了一个带有长时间运行线程和多个调用的小样本事件,没有遇到问题。你有没有感觉触发器方法被调用了多少次?这些调用是单线程还是多线程的? - IEE1394
我可以重现你的问题,使用50000次调用和一秒的延迟执行 - 所以我猜你在资源方面有麻烦。 - IEE1394
是的,也许您的应用程序没有足够的堆空间 - 请检查您的Xmx设置。创建50000个线程是一项严肃的任务;-) - IEE1394
@AlexandreDupriez 我认为这并没有回答问题,链接的答案也不是 - 还有第三种情况会导致 RejectedExecutionException 抛出 - 当线程无法创建时,池就会在这种情况下抛出它。 - Eugene
显示剩余5条评论

0

在触发方法之外创建ThreadPoolExecutor。您不应该为每个调用创建newSingleThreadExecutor

private ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private void trigger(final Packet packet) {

executorService .execute(new Runnable() {
  @Override
  public void run() {
    // some code here
  }
});

}

关于您的异常,请查看execute方法的描述。

public void execute(Runnable command)

在未来的某个时间执行给定的任务。该任务可以在新线程或现有池线程中执行。如果无法提交任务以供执行,可能是因为此执行程序已关闭或其容量已达到,因此当前的RejectedExecutionHandler处理该任务。 由于它是无界队列,很可能您在代码的其他位置调用了shutdown

那么你认为我应该创建一个固定大小的线程池,然后每次使用它而不是使用单个线程执行器? - user1950349
是的。在关机后不要向其提交任务。 - Ravindra babu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接