经过Spring的@Scheduled能够建立定时任务。spring
任务执行task:多线程
@Component @EnableScheduling public class TestDaemon { @Scheduled(cron = "0/10 * * * * *") public void testRunTask(){ try { Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } DateFormat df = new SimpleDateFormat("HH:mm:ss"); System.out.println(df.format(new Date()) + "********A任务每10秒执行一次进入测试"); } } @Scheduled(cron = "0/5 * * * * *") private void fullQueueTask() { System.out.println(new SimpleDateFormat("HH:mm:ss").format(new Date()) + "********B任务每5秒执行一次进入测试"); }
跑起来:并发
13:21:25********B任务每5秒执行一次进入测试 13:21:30********B任务每5秒执行一次进入测试 13:21:50********A任务每10秒执行一次进入测试 13:21:50********B任务每5秒执行一次进入测试 13:21:55********B任务每5秒执行一次进入测试 13:22:00********B任务每5秒执行一次进入测试 13:22:20********A任务每10秒执行一次进入测试 13:22:20********B任务每5秒执行一次进入测试 13:22:25********B任务每5秒执行一次进入测试
咱们发现B并无每隔5秒钟执行,而是当A任务启动后,B任务须要等待A任务执行完成以后继续执行。 这是由于默认的@Scheduled是单线程执行的,全部任务须要互相排队。异步
咱们在业务上确定须要不一样调度任务有本身的节奏,单线程是知足不了了,Spring为咱们提供了多线程的调度方式。测试
XML:线程
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> <task:annotation-driven scheduler="myScheduler" /> <!-- 配置任务线程池 --> <task:scheduler id="myScheduler" pool-size="5" /> </beans>
引入xml:code
<import resource="server-task.xml" />
再次执行:orm
13:26:00********B任务每5秒执行一次进入测试 13:26:05********B任务每5秒执行一次进入测试 13:26:10********B任务每5秒执行一次进入测试 13:26:15********B任务每5秒执行一次进入测试 13:26:20********B任务每5秒执行一次进入测试 13:26:20********A任务每10秒执行一次进入测试 13:26:25********B任务每5秒执行一次进入测试 13:26:30********B任务每5秒执行一次进入测试 13:26:35********B任务每5秒执行一次进入测试 13:26:40********B任务每5秒执行一次进入测试 13:26:45********B任务每5秒执行一次进入测试 13:26:50********A任务每10秒执行一次进入测试 13:26:50********B任务每5秒执行一次进入测试 13:26:55********B任务每5秒执行一次进入测试
咱们发现B任务是按照本身的节奏进行,每隔5秒执行一次。server
默认任务调度是单线程的,经过task:scheduler咱们能够建立一个对应的任务调度线程池执行任务,这样多任务调度就不须要串行执行了。xml
当咱们采用@Async异步执行逻辑时,使用的线程是task:executor中的线程,若是用@Async修饰一个调度任务,则调度线程池就会不用当前调度线程来执行,而是交给 task:executor 这个执行线程池来执行。
因此配置 task:scheduler 参数的线程池,只和调度任务有关,是为了根据任务总数来分配调度线程池的大小; 而配置 task:executor ,只和@Async异步任务有关,是为了某个任务若是要异步的执行时,实现当前任务内的多线程并发。
<task:annotation-driven scheduler="myScheduler" executor="myExecutor"/> <!-- 配置任务线程池 --> <task:scheduler id="myScheduler" pool-size="20" /> <task:executor id="myExecutor" pool-size="15-20" queue-capacity="1000" keep-alive="100ms" rejection-policy="CALLER_RUNS"/>