我有一个问题,我想要在运行时创建一个预定的任务。计划的任务应该以固定的速率触发。但是,现在我遇到的问题是手动设置计划不是以异步方式触发的。
主要的问题是,如果我们可以启动调度程序,那么我们就没有任何固定点。当我读取一个特定的值(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评论
这可以像预期的那样工作,但是我们无法使用它,因为我们必须在运行时创建调度程序,并在特定的时间/输入之后销毁它。
ScheduledTaskRegistrar 2.设置
代码
//@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而不是ThreadPoolTaskSchedulerConcurrentTaskScheduler以SimpleAsyncTaskExecutor为ConcurrentExecutorConcurrentTaskScheduler以ThreadPoolTaskExecutor为ConcurrentExecutor问题
如何使用测试2中描述的配置,但得到测试1的结果?有办法在测试2中描述的解决方案中使用@Async注释吗?还是有人对我的问题有更好的解决方案?
发布于 2020-04-01 19:48:18
是的,这是可能的。假设实现SchedulingConfigurer的类有一个方法doMyJob()。可以使用异步对该方法进行注释,并在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();
}
}
}希望它能帮上忙
编辑
我没有经过测试就提供了代码。最近,当我试图重新创建这个场景时,我注意到如果SchedulingConfigurer,中有doMyJob,那么它将不是真正的异步(如果延迟为5秒,作业需要10秒,下一个作业只在10秒之后运行)。但是,将方法移动到服务类会有所帮助。
https://stackoverflow.com/questions/57553786
复制相似问题