spring - 为什么与 Future 的 get 一起使用的 @Schedule 方法会阻止其他 @Schedule 方法

标签 spring spring-3 spring-scheduled

我有这个类

@Service
@Profile("async")
public class MyServiceImplAsync implements MyService {
..

    @Async
    @Override
    public void printGreetings(String name) {
        //do something and sleep 10 seconds
    }

    @Async
    @Override
    public Future<String> doSomething(String text) {
        //do something and sleep 25 seconds
        return new AsyncResult<String>(text);
    }

}

观察,这两种方法使用@Async
现在,我也有以下几点:
@Component
public class MySchedule {
..
    @Scheduled(cron="*/5 * * * * ?")
    public void schedule(){
        logger.info("Schedule working at {}", simpleDateFormat.format( new Date() ));
        this.myService.printGreetings("Manolito");
    }

    @Scheduled(cron="*/30 * * * * ?")
    public void scheduleFuture(){
        logger.info("Schedule Future working at {}", simpleDateFormat.format( new Date() ));

        try {
            logger.info("{}", this.myService.doSomething("manolito").get(26, TimeUnit.SECONDS));
        } 
        catch (InterruptedException | ExecutionException | TimeoutException e) {
            logger.error("Error: {}, Class: {}", e.getMessage(), e.getClass());
        }
    }

}
schedule()方法必须每 5 秒执行一次,scheduleFuture()方法必须每 30 秒执行一次。

我对以下情况感到困惑:

我可以看到 schedule()方法每5秒平安工作,然后当scheduleFuture()开始运行,scheduleFuture()由于 Future 的方法 获取 方法,保持阻塞。我对此很好,因为这是符合 Future API 的预期行为.

我想:

Only the scheduleFuture() method should be blocked.



问题 : 我不明白为什么scheduleFuture()阻止另一个 schedule()方法太!。我的意思是如果 scheduleFuture()被屏蔽了,schedule()仍然被封锁了!。它不能开始新的循环或执行。直到scheduleFuture()再次解锁。

为什么会出现这种情况?

我有 两个 @Scheduled方法,每一个调用 两个不同 @Async 注释的方法一个 bean(如果 MyServiceImplAsync 类是 @Scope("prototype"),情况相同

提前致谢。

最佳答案

因为您正在阻塞用于调度这些任务的单个线程。来自 @EnableScheduling :

In all of the above scenarios, a default single-threaded task executor is used. When more control is desired, a @Configuration class may implement SchedulingConfigurer. This allows access to the underlying ScheduledTaskRegistrar instance.


@Configuration
@EnableScheduling
public class AppConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean(destroyMethod="shutdown")
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(100);
    }
}

当您遇到此类问题时,一个好主意是配置您的日志记录框架以显示线程的名称。使用log4j,需要添加%t给您的 PatternLayout

关于spring - 为什么与 Future 的 get 一起使用的 @Schedule 方法会阻止其他 @Schedule 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25131052/

相关文章:

spring - Javax 验证

java - Spring 数据 Neo4J 4.0.0 : BeforeSaveEvent not firing?

java - Spring 3.0如何使用方法拦截器?

java - spring-boot @scheduled 没有在不同的线程中运行?

java - 在同一个表的同一事务中绑定(bind) springjdbc 和 hibernate session 工厂

java - Heroku Slug 尺寸超出限制 超过 300m

hibernate - 在 Spring 中设置 Hibernate session 的刷新模式

java - 在独立应用程序中使用 spring 所需的最少 jar 是什么?

java - Spring 计划任务不会在应用程序启动时启动

java - 测试 Spring Scheduler 每年安排一次的作业