Java ThreadPoolTaskExecutor抛出RejectedExecutionException

Java ThreadPoolTaskExecutor抛出RejectedExecutionException,java,spring,spring-boot,java.util.concurrent,completable-future,Java,Spring,Spring Boot,Java.util.concurrent,Completable Future,我希望实现以下行为: 从文件中读取n个事件 在线程中处理它们 如果仍有任何事件,请返回步骤1 我编写了以下应用程序来测试解决方案,但它在随机时刻失败了,例如 java.lang.IllegalStateException: Failed to execute CommandLineRunner Caused by: org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadP

我希望实现以下行为:

  • 从文件中读取n个事件
  • 在线程中处理它们
  • 如果仍有任何事件,请返回步骤1
  • 我编写了以下应用程序来测试解决方案,但它在随机时刻失败了,例如

    java.lang.IllegalStateException: Failed to execute CommandLineRunner
    Caused by: org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadPoolExecutor@62b3df3a[Running, pool size = 5, active threads = 4, queued tasks = 0, completed tasks = 70]] did not accept task: java.util.concurrent.CompletableFuture$AsyncSupply@71ea1fda
    
    如果我不想将事件放入队列,我应该设置什么队列容量?我想马上处理它们

    我使用的是OpenJDK11和SpringBoot2.2.2.0版本

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CompletableFuture;
    import java.util.stream.Collectors;
    
    @SpringBootApplication
    public class DemoApplication implements CommandLineRunner {
    
        @Autowired
        private ThreadPoolTaskExecutor eventExecutor;
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
        @Bean(name = "eventExecutor")
        public ThreadPoolTaskExecutor eventExecutor() {
            ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
            pool.setCorePoolSize(5);
            pool.setMaxPoolSize(5);
            pool.setQueueCapacity(0);
            pool.setAwaitTerminationSeconds(0);
            pool.initialize();
            return pool;
        }
    
        @Override
        public void run(String... args) {
            System.out.println("Start events processing");
            long start = System.currentTimeMillis();
    
            int result = 0;
            for (int i = 0; i < 100; i++) {
                List<CompletableFuture<Integer>> completableFutures = getEvents(5).stream()
                        .map(event -> CompletableFuture.supplyAsync(() -> processEvent(event), eventExecutor))
                        .collect(Collectors.toList());
    
                result += completableFutures.stream()
                        .mapToInt(CompletableFuture::join)
                        .sum();
            }
    
            long timeMillis = System.currentTimeMillis() - start;
    
            System.out.println("Took " + timeMillis + "ms, " + result);
        }
    
        private List<Event> getEvents(int n) {
            List<Event> events = new ArrayList<>();
            for (int i = 1; i <= n; i++) {
                events.add(new Event(i));
            }
            return events;
        }
    
        private int processEvent(Event event) {
            System.out.println("processing event " + event.id);
    
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("processing event " + event.id + " finished");
    
            return 1;
        }
    
        private static class Event {
    
            private int id;
    
            private Event(int id) {
                this.id = id;
            }
        }
    }
    
    import org.springframework.beans.factory.annotation.Autowired;
    导入org.springframework.boot.CommandLineRunner;
    导入org.springframework.boot.SpringApplication;
    导入org.springframework.boot.autoconfigure.springboot应用程序;
    导入org.springframework.context.annotation.Bean;
    导入org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    导入java.util.ArrayList;
    导入java.util.List;
    导入java.util.concurrent.CompletableFuture;
    导入java.util.stream.collector;
    @SpringBoot应用程序
    公共类DemoApplication实现CommandLineRunner{
    @自动连线
    私有线程池任务执行器事件执行器;
    公共静态void main(字符串[]args){
    run(DemoApplication.class,args);
    }
    @Bean(name=“eventExecutor”)
    公共线程池TaskExecutor eventExecutor(){
    ThreadPoolTaskExecutor池=新的ThreadPoolTaskExecutor();
    池。setCorePoolSize(5);
    pool.setMaxPoolSize(5);
    池。设置队列容量(0);
    pool.SetWaitingTerminationSeconds(0);
    pool.initialize();
    回流池;
    }
    @凌驾
    公共无效运行(字符串…参数){
    System.out.println(“启动事件处理”);
    长启动=System.currentTimeMillis();
    int结果=0;
    对于(int i=0;i<100;i++){
    List completableFutures=getEvents(5).stream()
    .map(事件->CompletableFuture.SupplySync(()->processEvent(事件),eventExecutor))
    .collect(Collectors.toList());
    结果+=completableFutures.stream()
    .mapToInt(CompletableFuture::join)
    .sum();
    }
    long-timeMillis=System.currentTimeMillis()-开始;
    System.out.println(“take”+timeMillis+“ms”+result);
    }
    私有列表getEvents(int n){
    列表事件=新建ArrayList();
    
    对于(int i=1;i我建议将
    pool.setQueueCapacity(0)
    更改为使用正值,以便在如此配置的固定大小池(corePoolSize==maxPoolSize==5)中没有可用线程时,允许任务排队处理

    输出“pool size=5,active threads=4”显示了线程的大致数量


    从理论上讲,在尝试处理新的一批事件之前,线程可能不会返回到池中。

    您可能需要池中的更多线程来处理每个线程的每个任务,而不排队,或者增加队列大小,以便在线程忙时任务可以排队