經過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"/>