spring @Scheduled带注释的方法是否在不同的线程上运行?

时间:2014-02-24 16:34:09

标签: java spring scheduled-tasks

我有几个用@Scheduled注释的方法(fixedDelay = 10000)。

在应用程序上下文中,我有这个注释驱动设置:

<task:annotation-driven />

问题是,有时一些方法执行会延迟几秒甚至几分钟。

我假设即使方法需要一段时间才能完成执行,其他方法仍然会执行。所以我不明白延迟。

有没有办法可以减少甚至消除延迟?

9 个答案:

答案 0 :(得分:45)

为了完整性,下面的代码显示了使用java config配置调度程序的最简单方法:

@Configuration
@EnableScheduling
public class SpringConfiguration {

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

如果需要更多控制权,@Configuration类可以实施SchedulingConfigurer

答案 1 :(得分:42)

documentation about scheduling说:

  

如果您不提供pool-size属性,则默认线程池将只有一个线程。

因此,如果您有许多计划任务,您应该按照文档中的说明配置调度程序,以使池具有更多线程,以确保一个长任务不会延迟所有其他任务。

答案 2 :(得分:19)

使用@Scheduled注释的方法意味着在不同的线程上单独运行。

如果您的配置中未提供TaskScheduler,则Spring将使用

Executors.newSingleThreadScheduledExecutor();

返回在单个线程上运行的ScheduledExecutorService。因此,如果您有多个@Scheduled方法,虽然它们已被调度,但它们每个都需要等待线程完成执行上一个任务。随着队列填满的速度快于排空,你可能会继续变得越来越大。

确保使用适当数量的线程配置您的计划环境。

答案 3 :(得分:7)

你可以使用:

@Bean()
public  ThreadPoolTaskScheduler  taskScheduler(){
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(2);
    return  taskScheduler;
}

答案 4 :(得分:2)

@EnableScheduling注释提供了关键信息以及如何解决它:

  

默认情况下,将搜索关联的调度程序定义:   上下文中的唯一TaskScheduler bean或TaskScheduler   否则,将其命名为“ taskScheduler”。同样的查询也将是   为ScheduledExecutorService bean执行。 如果两者都不存在   是可解决的,本地单线程默认调度程序将是   在注册商内部创建并使用

     

当需要更多控制时,可以实现@Configuration类   SchedulingConfigurer。这允许访问底层   ScheduledTaskRegistrar实例。例如,下面的例子   演示如何自定义用于执行计划的执行器   任务:

 @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);
     }
 }

(添加了重点)

答案 5 :(得分:1)

更新2019

您还可以在应用程序属性文件中设置一个属性,以增加池的大小:

tts = new TextToSpeech(Level_11_Testing.this, new TextToSpeech.OnInitListener() { public void onInit(int status) { if (status != TextToSpeech.ERROR) { tts.setLanguage(Locale.US); tts.speak("Push on" + rightchoice, TextToSpeech.QUEUE_ADD, null); } } }); up.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { up.setEnabled(false);//it prevents double clicking if (idx == rightchoice) { tts.speak("Good job, clap!", TextToSpeech.QUEUE_FLUSH, null); mHandler.postDelayed(hMyTimeTask, 1400); } else { tts.speak("Try again!", TextToSpeech.QUEUE_FLUSH, null); }

似乎从Spring Boot 2.1.0开始存在。

答案 6 :(得分:0)

使用单个线程执行调度任务的默认弹簧。您可以将@Configuration用于类实现SchedulingConfigurer。推荐人:https://crmepham.github.io/spring-boot-multi-thread-scheduling/

答案 7 :(得分:0)

使用XML文件在下面添加行。

<task:scheduler id="taskScheduler" pool-size="15" />
<task:scheduled-tasks scheduler="taskScheduler" >
....
</task:scheduled-tasks>

答案 8 :(得分:-1)