javascript
Spring 使用介绍(十二)—— Spring Task
一、概述
1、jdk的線程池和任務調用器分別由ExecutorService、ScheduledExecutorService定義,繼承關系如下:
ThreadPoolExecutor:ExecutorService的實現類,其構造函數提供了靈活的參數配置,可構造多種類型的線程池,詳細可參考JAVA進階----ThreadPoolExecutor機制
ScheduledThreadPoolExecutor:ScheduledExecutorService的實現類,用于任務調度
?
2、spring task對定時任務的兩個抽象:
- TaskExecutor:與jdk中Executor相同,引入的目的是為定時任務的執行提供線程池的支持
- TaskScheduler:對定時任務的抽象
繼承關系如下:
任務執行器與調度器的實現類分別為ThreadPoolTaskExecutor、ThreadPoolTaskScheduler
TaskScheduler需要傳入一個Runnable的任務做為參數,并指定需要周期執行的時間或者觸發器(Trigger)。
spring定義了Trigger接口的實現類CronTrigger,支持使用cron表達式指定定時策略,使用如下:
scheduler.schedule(task, new CronTrigger("30 * * * * ?"));?
二、定時任務
spring定時任務的使用和配置非常簡單,支持xml配置和注解兩個方式
1、XML配置方式
任務類
@Component public class TestTask {public void job() {System.out.println("hello matt!");} }配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd"> <context:component-scan base-package="cn.matt.schedule"/> <!-- 任務調度器--><task:scheduler id="myScheduler" pool-size="10"/> <!-- 任務配置--><task:scheduled-tasks scheduler="myScheduler"> <task:scheduled ref="testTask" method="job" cron="0/2 * * * * ?"/> </task:scheduled-tasks> </beans>測試
public class TaskTest {@Testpublic void test() throws InterruptedException {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-context.xml");TimeUnit.SECONDS.sleep(10);} }2、注解方式
?任務類
@Component public class TestTask {@Scheduled(cron = "0/2 * * * * ?")public void job() {System.out.println("hello matt!");} }配置
<!-- 任務調度器--> <task:scheduler id="myScheduler" pool-size="10"/> <!-- 開啟任務注解--> <task:annotation-driven scheduler="myScheduler"/>測試代碼與xml配置方式相同
補充說明:
- 使用<task:executor>配置任務執行器,即實例化ThreadPoolTaskExecutor
- 使用<task:scheduler>配置任務調度器,即實例化ThreadPoolTaskScheduler
- 兩種方式的任務調度器不指定時,默認會使用只有一個線程的調用器,關于配置的詳細介紹和默認參數,可參考xsd文檔?http://www.springframework.org/schema/task/spring-task-4.1.xsd
疑問:
有些項目同時指定任務執行器和調度器,如下:
<!-- 啟用注解驅動的定時任務 --> <task:annotation-driven scheduler="myScheduler" executor="myExecutor"/> <!-- 配置定時任務的線程池 --> <task:scheduler id="myScheduler" pool-size="10"/> <task:executor id="myExecutor" pool-size="10" />存在兩個線程池,兩者的關系是怎樣的?執行器用的是哪個線程池?
經驗證,定時任務執行時,使用的是任務調度器的線程池,任務執行器的設置對定時任務的執行沒有影響,測試代碼如下:
任務類
@Component public class TestTask {@Scheduled(cron = "0/5 * * * * ?")public void job1() {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(String.format("%s*******%s", sdf.format(new Date()), "job1"));}@Scheduled(cron = "0/10 * * * * ?")public void job2() {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(String.format("%s*******%s", sdf.format(new Date()), "job2"));try {TimeUnit.SECONDS.sleep(15);} catch (InterruptedException e) {}} } View Code?配置與疑問中相同
測試(測試時,通過改變線程池的大小進行驗證)
public class TaskTest {@Testpublic void test() throws InterruptedException {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-context.xml");TimeUnit.SECONDS.sleep(1000);} } View Code?
3、cron表達式
spring支持6個參數的cron表達式,格式如下:
{秒} {分} {時} {日期} {月} {星期}- 秒:必填項,允許的值范圍是0-59,支持的特殊符號包括'-*/,',','表示特定的某一秒才會觸發任務,'-'表示一段時間內會觸發任務,'*'表示每一秒都會觸發,'/'表示從哪一個時刻開始,每隔多長時間觸發一次任務。
- 分:必填項,允許的值范圍是0-59,支持的特殊符號和秒一樣,含義類推
- 時:必填項,允許的值范圍是0-23,支持的特殊符號和秒一樣,含義類推
- 日期:必填項,允許的值范圍是1-31,支持的特殊符號相比秒多了?,表示與{星期}互斥,即意味著若明確指定{星期}觸發,則表示{日期}無意義,以免引起沖突和混亂
- 月:必填項,允許的值范圍是1-12(JAN-DEC),支持的特殊符號與秒一樣,含義類推
- 星期:必填項,允許值范圍是1~7 (SUN-SAT),1代表星期天(一星期的第一天),以此類推,7代表星期六,支持的符號相比秒多了?,表達的含義是與{日期}互斥,即意味著若明確指定{日期}觸發,則表示{星期}無意義。
示例:
0 0 12 * * ? 每天中午12點觸發 0 * 14 * * ? 每天下午2點到下午2:59期間的每1分鐘觸發 0 0/5 14 * * ? 每天下午2點到下午2:55期間的每5分鐘觸發 0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44觸發關于cron表達式的詳細介紹可參考spring定時任務詳解
?
三、異步調用
spring提供@Async注解,可很方便的實現異步調用,簡單示例如下:
接口及實現類
public interface Hello {void doSomething1();void doSomething2(); } @Component public class HelloImpl implements Hello {@Async@Overridepublic void doSomething1() {System.out.println(String.format("thread:%d **** doSomething1", Thread.currentThread().getId()));}@Async("myExecutor2")@Overridepublic void doSomething2() {System.out.println(String.format("thread:%d **** doSomething2", Thread.currentThread().getId()));} }配置
<context:component-scan base-package="cn.matt.schedule"/> <!-- 開啟@Async注解支持 --> <task:annotation-driven executor="myExecutor1"/> <!-- 定義執行器 --> <task:executor id="myExecutor1" pool-size="10" /> <task:executor id="myExecutor2" pool-size="10" />測試
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring-context.xml") public class SpringTestBase {} public class AsyncTest extends SpringTestBase {@Autowiredprivate Hello hello;@Testpublic void test() {System.out.println(String.format("main thread:%d **** doSomething1", Thread.currentThread().getId()));hello.doSomething1();hello.doSomething2();} }// 輸出: // main thread:1 **** doSomething1 // thread:20 **** doSomething2 // thread:19 **** doSomething1說明:@Async默認使用<task:annotation-driven/>指定的執行器,當存在多個執行器時,可通過@Async的value屬性單獨指定
?
參考:
Spring任務調度之Spring-Task
spring定時任務詳解(@Scheduled注解)
深入淺出Spring task定時任務
?Spring異步任務處理,@Async的配置和使用
Spring中@Async
轉載于:https://www.cnblogs.com/MattCheng/p/9052140.html
總結
以上是生活随笔為你收集整理的Spring 使用介绍(十二)—— Spring Task的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爬虫批量下载全站小说并自动保存
- 下一篇: gradle idea java ssm