我有几个用@Scheduled注释的方法(fixedDelay = 10000)。
在应用程序上下文中,我有这个注释驱动设置:
<task:annotation-driven />
问题是,有时一些方法执行会延迟几秒甚至几分钟。
我假设即使方法需要一段时间才能完成执行,其他方法仍然会执行。所以我不明白延迟。
有没有办法可以减少甚至消除延迟?
答案 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)
您还可以在应用程序属性文件中设置一个属性,以增加池的大小:
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)