抽奖怎么做网站,网站开元棋牌怎么做app,WordPress文章相关阅读设置,欧美设计网站推荐在开发Spring Boot应用程序时#xff0c;定时任务是一项常见的需求。Spring Boot提供了Scheduled注解#xff0c;可用于将方法标记为定时任务#xff0c;并在预定的时间间隔内执行。那么Scheduled注解的执行方式是单线程执行#xff0c;还是多线程执行#xff1f;Schedule…在开发Spring Boot应用程序时定时任务是一项常见的需求。Spring Boot提供了Scheduled注解可用于将方法标记为定时任务并在预定的时间间隔内执行。那么Scheduled注解的执行方式是单线程执行还是多线程执行Scheduled注解的执行方式会不会产生线程不安全的问题
以下总结Scheduled注解的执行方式并解释它在Spring Boot中的多线程行为。
一案例演示
新建两个定时任务一个是每2秒执行一次一个是每3秒执行一次
Component
public class ScheduledTest {Scheduled(cron 0/2 * * * * ? )public void testTask1(){Thread thread Thread.currentThread();String threadName thread.getName();System.out.println(threadName-- testTask1--LocalDateTime.now());}Scheduled(cron 0/3 * * * * ? )public void testTask2(){Thread thread Thread.currentThread();String threadName thread.getName();System.out.println(threadName--testTask2-- LocalDateTime.now());}
}发现这两个任务的线程是同一个由此可以推测Spring Boot提供的Scheduled注解默认是以单线程方式执行。下面看下源码Scheduled提供的核心类ScheduledTaskRegistrar、ContextLifecycleScheduledTaskRegistrar ContextLifecycleScheduledTaskRegistrar 在bean实例化后会调 其父类ScheduledTaskRegistrar提供的scheduleTasks()方法并且创建了单例的调度线程池 由此可见Spring Boot提供的Scheduled注解默认是以单线程方式执行。
有的人可能会想会不会是在同一个类中的方法导致结果是公用了同一个线程不要猜去验证 把testTask1和testTask2分别放在不同的类结果共用同一个线程。
二在单线程下会产生什么问题
单线程环境下如果某个任务处理时间很长有可能导致其他任务阻塞。testTask1()休眠一小时模拟长时间处理任务testTask2()一直处于阻塞状态。
Component
public class ScheduledTest1 {Scheduled(cron 0/2 * * * * ? )public void testTask1() throws InterruptedException {Thread thread Thread.currentThread();String threadName thread.getName();System.out.println(testTask1 开始执行~);TimeUnit.HOURS.sleep(1);System.out.println(threadName -- testTask1-- LocalDateTime.now());}Scheduled(cron 0/3 * * * * ? )public void testTask2() {Thread thread Thread.currentThread();String threadName thread.getName();System.out.println(threadName -- testTask2-- LocalDateTime.now());}
}因此对于这种场景我们可以考虑把Scheduled配置成多线程环境下执行解决Scheduled在单线程环境下可能产生的问题。
三Scheduled支持多线程吗
既然SchedulingConfigurer默认是创建了单例线程池那我们是不是可以自定义线程池当做参数传给Scheduled呢
Configuration
public class ScheduleConfig implements SchedulingConfigurer {Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));}
}案例验证代码
Component
public class ScheduledTest6 {Scheduled(cron 0/2 * * * * ? )public void testTask1() throws InterruptedException {Thread thread Thread.currentThread();String threadName thread.getName();System.out.println(testTask1 开始执行~);TimeUnit.HOURS.sleep(1);System.out.println(threadName -- testTask1-- LocalDateTime.now());}Scheduled(cron 0/3 * * * * ? )public void testTask2() {Thread thread Thread.currentThread();String threadName thread.getName();System.out.println(threadName -- testTask2-- LocalDateTime.now());}
}由截图可知有5个线程1、2、5都正常处理testTask2任务3、4两个线程正在处理testTask1()任务因此多线程环境下可以解决单线程环境下可能导致的任务阻塞的问题。 更多细节可以关注我的个人主页 www.zhouy.work