我无法通过ExecutorService获取RejectedExecutionException

时间:2018-10-22 08:37:01

标签: java executorservice executor

我创建了调度程序来测试RejectedExecutionException的处理:

@Component
public class TestScheduler {

    private final TestService testService;
    private ExecutorService executorService;

    public TestScheduler(TestService testService) {
        this.testService = testService;
    }

    @PostConstruct
    public void init() {
        executorService = Executors.newFixedThreadPool(5);
    }

    @Scheduled(fixedRate = 10L)
    public void test() {
        System.out.println("test");
        executorService.execute(testService::print);
    }
}

服务延迟70秒:

@Component
public class TestService {

    public void print() {
        System.out.println("print start");
        try {
            TimeUnit.SECONDS.sleep(70);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("print end");
    }
}

我等待下一个逻辑:

  1. 调度程序呼叫executorService.execute(testService::print) 5次
  2. 每个testService::print将执行70秒
  3. execute方法将第六次调用时,我得到RejectedExecutionException

但是我没有得到异常。我有这个日志:

test
print start
2018-10-22 11:26:45.543  INFO 5960 --- [           main] c.e.s.SchedullerExceptionsApplication    : Started SchedullerExceptionsApplication in 0.661 seconds (JVM running for 1.108)
test
print start
test
print start
test
print start
test
print start
test
...
70 seconds print test

编辑

在实际项目中,我有以下代码:

@PostConstruct
    public void init() {
        executorService = Executors.newFixedThreadPool(100, new CustomizableThreadFactory("SendRequestExecutor-"));
    }

@Scheduled(fixedDelay = 1000L)
public void sendReady() {
    try {
        List<Message> messages = messageService.findReadyToSend();
        for (Message message : messages) {
            message.setStatus(IN_PROCESS);
            Message savedMessage = messageService.save(message);
            executorService.execute(() -> sendRequestService.send(savedMessage.getGuid()));
        }
    } catch (Exception e) {
        log.error("handle: " + e.getMessage());
    }
}

这是否意味着此代码是错误的?因为会发生这种情况,所以我将实体更改为状态IN_PROCESS,并在尝试执行时-如果executorService已满,我不会出现异常,而executorService不会执行我的任务吗?

2 个答案:

答案 0 :(得分:2)

定义执行程序时涉及两个方面。

  1. 执行器将使用的线程数。这限制了执行器可以运行的并发任务数。这是您通过Executors.newFixedThreadPool(5)进行的设置。
  2. 基础任务提交队列的大小。这限制了基础队列可以存储的任务数量,直到引发异常为止。由newFixedThreadPool创建的执行程序使用无限制的队列,因此不会出现异常。

您可以通过如下创建自己的执行程序服务并向其提交11个任务(5个使用所有线程,5个填充底层任务队列和1个溢出任务)来实现所需的行为。

new ThreadPoolExecutor(5, 
                       5, 
                       2000L, 
                       TimeUnit.MILLISECONDS, 
                       new ArrayBlockingQueue<Runnable>(5, true), 
                       new ThreadPoolExecutor.CallerRunsPolicy());

答案 1 :(得分:0)

RejectedExecutionException将被抛出给您溢出任务队列(目前尚未绑定),而您希望在安排更多任务时将其抛出(放入可能不受限制的队列) ),那么您就有了工作人员-多数民众赞成在这是工作人员的目的-建立队列并从中执行。

要测试错误处理,请模拟执行器并在任务提交时抛出异常(最好),或者使用有限,有界,无阻塞的队列作为执行器的后备队列。

使用模拟是最简单的方法。