Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我无法通过ExecutorService获得RejectedExecutionException_Java_Executorservice_Executor - Fatal编程技术网

Java 我无法通过ExecutorService获得RejectedExecutionException

Java 我无法通过ExecutorService获得RejectedExecutionException,java,executorservice,executor,Java,Executorservice,Executor,我创建Scheduler以处理被拒绝的执行异常: @Component public class TestScheduler { private final TestService testService; private ExecutorService executorService; public TestScheduler(TestService testService) { this.testService = testService;

我创建Scheduler以处理被拒绝的执行异常:

@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");
    }
}
我等待下一个逻辑:

  • 调度程序调用executorService.execute(testService::print)5次
  • 每个
    testService::print
    将执行70秒
  • 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
    
    编辑

    在real project中,我有以下代码:

    @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());
        }
    }
    
    @PostConstruct
    公共void init(){
    executorService=Executors.newFixedThreadPool(100,新的CustomizelThreadFactory(“SendRequestExecutor-”);
    }
    @计划(固定延迟=1000L)
    public void sendReady(){
    试一试{
    List messages=messageService.findReadyToSend();
    用于(消息:消息){
    message.setStatus(进程中);
    Message savedMessage=messageService.save(Message);
    executorService.execute(()->sendRequestService.send(savedMessage.getGuid());
    }
    }捕获(例外e){
    log.error(“句柄:+e.getMessage());
    }
    }
    

    这是否意味着该代码是错误的?因为这可能会发生,所以我会将实体更改为流程中的状态
    ,当尝试执行时-如果
    executorService
    已满,我不会得到异常,并且
    executorService
    不会执行我的任务

    RejectedExecutionException
    将被抛出到您的溢出任务队列中(现在是未绑定的),而您希望在安排更多任务时抛出它(将其放入可能未绑定的队列中)然后您就有了工作者——这是不存在的,因为这是工作者的一种目的——来构建队列并从中执行

    要测试错误处理,可以模拟您的执行者并在任务提交时抛出异常(首选),或者使用有限、有界、非阻塞队列作为您的执行者的支持队列


    使用mock是最简单的方法。

    RejectedExecutionException
    将向您抛出溢出任务队列(现在是未绑定的),而您希望在安排更多任务时抛出它(将其放入可能未绑定的队列)然后您就有了工作者——这是不存在的,因为这是工作者的一种目的——来构建队列并从中执行

    要测试错误处理,可以模拟您的执行者并在任务提交时抛出异常(首选),或者使用有限、有界、非阻塞队列作为您的执行者的支持队列


    使用mock是最简单的方法。

    定义执行器时涉及两个方面

  • 执行器将使用的线程数。这限制了执行器可以运行的并发任务数。这是您通过执行器来设置的。newFixedThreadPool(5)
  • 基础任务提交队列的大小。这限制了基础队列可以存储的任务数量,直到它抛出异常为止。由
    newFixedThreadPool
    创建的执行器使用无界队列,因此不会出现异常
  • 通过如下创建自己的executor服务并向其提交11个任务(5个用于使用所有线程,5个用于填充底层任务队列,1个用于使其溢出),您可以实现所需的行为

    新线程池执行器(5,
    5.
    2000L,
    TimeUnit.ms,
    新的ArrayBlockingQueue(5,true),
    新的ThreadPoolExecutor.CallerRunPolicy());
    
    定义执行者时涉及两个方面

  • 执行器将使用的线程数。这限制了执行器可以运行的并发任务数。这是您通过执行器来设置的。newFixedThreadPool(5)
  • 基础任务提交队列的大小。这限制了基础队列可以存储的任务数量,直到它抛出异常为止。由
    newFixedThreadPool
    创建的执行器使用无界队列,因此不会出现异常
  • 通过如下创建自己的executor服务并向其提交11个任务(5个用于使用所有线程,5个用于填充底层任务队列,1个用于使其溢出),您可以实现所需的行为

    新线程池执行器(5,
    5.
    2000L,
    TimeUnit.ms,
    新的ArrayBlockingQueue(5,true),
    新的ThreadPoolExecutor.CallerRunPolicy());
    
    我提出了一个问题。看please@ip696代码没有错。该executor服务定义使用一个无界任务队列,因此不会出现异常。如果您想获得溢出异常,请更改executor的创建方式。aaa,似乎,我理解您的意思)这在我看来是一个来自5个线程的池,但队列不受限制。当池已满时—新线程被放入队列中,当它们完成时,会从队列中替换它们吗?那么在这种情况下,如果我的调度程序将超过执行器很多,我只能得到内存溢出(执行器队列将非常大)?是的,这是正确的,任务被添加到(无界)任务队列并等待可用线程。它只能在内存不足的情况下失败。我提出了一个问题。看please@ip696代码没有错。该executor服务定义使用一个无界任务队列,因此不会出现异常。如果您想获得溢出异常,请更改executor的创建方式。aaa,似乎,我理解您的意思)这在我看来是一个来自5个线程的池,但队列不受限制。当池已满时—新线程被放入队列中,当它们完成时,会从队列中替换它们吗?
    new ThreadPoolExecutor(5, 
                           5, 
                           2000L, 
                           TimeUnit.MILLISECONDS, 
                           new ArrayBlockingQueue<Runnable>(5, true), 
                           new ThreadPoolExecutor.CallerRunsPolicy());