代码之家  ›  专栏  ›  技术社区  ›  user1950349

来自单线程执行器的RejectedExecutionException

  •  5
  • user1950349  · 技术社区  · 7 年前

    下面是我的方法,其中我有单线程执行器来执行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 方法被多次调用,它仍然在我以前的线程中的run方法上工作?它会启动同样多的线程,还是等待一个线程完成,然后启动另一个线程?

    2 回复  |  直到 7 年前
        1
  •  1
  •   IEE1394    7 年前

    请参见此处: What could be the cause of 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();
        }
    }
    
        2
  •  0
  •   Ravindra babu    7 年前

    创造 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 代码中的其他部分。