我有一个问题,我想在运行时创建计划任务。计划任务应以固定速率触发。但是现在,我遇到了一个问题,即手动设置计划没有以异步方式触发。
主要问题是,我们没有任何固定点可以启动调度程序。当我读取特定值(1)时应该创建它,而当值改回(0)时它应该被破坏。否则,我们可以使用下面测试1中描述的注释配置。
到目前为止,我已经尝试过:
1。安排@Scheduled(fixedRate = 500L)
和@Async
代码
@Async
@Scheduled(fixedRate = 500L)
public void annotationTest() {
UUID id = UUID.randomUUID();
log.warn("Hello from Thread {} going to sleep", id);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.warn("Finished Thread {}", id);
}
在类级别上还具有@EnableAsync
和@EnableScheduling
注释。
结果
09:56:24.855 [task-5] : Hello from Thread 3b5514b2-3b80-4641-bf12-2cd320c4b6e5 going to sleep
09:56:25.355 [task-6] : Hello from Thread e98514a7-e193-422b-9569-f7635deb33f8 going to sleep
09:56:25.356 [task-4] : Finished Thread d86f5f24-bffb-4ddd-93fe-2334ed48cf91
09:56:25.854 [task-7] : Hello from Thread cfc2ab03-4e7e-4a4a-aa08-41d696cb6df7 going to sleep
09:56:25.855 [task-5] : Finished Thread 3b5514b2-3b80-4641-bf12-2cd320c4b6e5
09:56:26.355 [task-6] : Finished Thread e98514a7-e193-422b-9569-f7635deb33f8
评论
这可以按预期工作,但是我们无法使用它,因为我们必须在运行时创建调度程序,并在特定时间/输入之后销毁它。
2。设置ScheduledTaskRegistrar
代码
//@Configuration
@Bean
public ScheduledTaskRegistrar scheduledTaskRegistrar() {
ScheduledTaskRegistrar scheduledTaskRegistrar = new ScheduledTaskRegistrar();
scheduledTaskRegistrar.setScheduler(threadPoolTaskScheduler());
return scheduledTaskRegistrar;
}
@Bean
public TaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(20);
return scheduler;
}
//@Component
public void printMessages() {
scheduledTaskRegistrar.scheduleFixedRateTask(new FixedRateTask(new OwnRunnable(), 500L, 0L));
}
OwnRunnable
也将休眠1秒钟,然后再打印完成的文本
结果
10:13:56.983 [TaskScheduler-1] : Finished Thread 73f70de9-35d9-47f0-801b-fb2857ab1c34
10:13:56.984 [TaskScheduler-3] : Hello from Thread 7ab16380-8dba-49e1-bf0d-de8235f81195 going to sleep
10:13:57.984 [TaskScheduler-3] : Finished Thread 7ab16380-8dba-49e1-bf0d-de8235f81195
10:13:57.984 [TaskScheduler-2] : Hello from Thread cc152d2e-f93b-4770-ac55-853a4dd6be97 going to sleep
10:13:58.985 [TaskScheduler-2] : Finished Thread cc152d2e-f93b-4770-ac55-853a4dd6be97
10:13:58.985 [TaskScheduler-4] : Hello from Thread 8d4510a4-773d-49f3-b51b-e58e425b0b68 going to sleep
评论
我们可以看到任务以同步方式运行,不符合我们的要求。
3。其他测试
所有其他测试与2中描述的测试相似,但将使用ScheduledTaskRegistrar
的其他一些配置。结果与测试2相同。
ConcurrentTaskScheduler
而非ThreadPoolTaskScheduler
ConcurrentTaskScheduler
,其中SimpleAsyncTaskExecutor
为ConcurrentExecutor
ConcurrentTaskScheduler
,其中ThreadPoolTaskExecutor
为ConcurrentExecutor
问题
如何使用测试2中所述的配置,但获得测试1的结果?有没有一种方法可以将@Async
注释与测试2中所述的解决方案一起使用?还是有人对我的问题有更好的/其他解决方案?
答案 0 :(得分:3)
是的,有可能。假设实现SchedulingConfigurer的类具有方法doMyJob()。您可以使用Async注释该方法,并在FixedRateTask中使用引用。还要注意班级注释
@Configuration
@EnableAsync
public class MyJobConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.scheduleFixedRateTask(new FixedRateTask(this::doMyJob, 500L, 0L));
}
@Async
public void doMyJob() {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
希望有帮助
编辑
我提供的代码未经测试。最近,当我尝试重新创建此方案时,我注意到如果 doMyJob 在 SchedulingConfigurer 内,则不会真正异步(如果延迟为5秒,而作业需要10秒,则下一个作业仅在10秒后运行)。但是将方法移到服务类上很有帮助。