1、Spring異步任務
開啓異步配置(@EnableAsync註解指定或<task:annotation-driven>標籤配置)
1、用Java註解:
第一步:在類的申明前使用@EnableAsync註解開啓異步調用功能。
第二步:public AsyncTaskExecutor taskExecutor() 方法自定義自己的線程池,線程池前綴”Anno-Executor”。如果不定義,則使用系統默認的線程池。
@EnableAsync // 啓動異步調用
public class AsyncApplicationWithAnnotation {
/* 略 */
/**
* 自定義異步線程池
* @return
*/
@Bean
public AsyncTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setThreadNamePrefix("Anno-Executor");
executor.setMaxPoolSize(10);
// 設置拒絕策略
executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// .....
}
});
return executor;
}
}
2、用XML配置:
第一步:使用<task:executor>標籤定義線程池
第二步:使用<task:annotation-driven>標籤啓動異步線程池配置
如下spring-async.xml配置:
<!-- 等價於 @EnableAsync, executor指定線程池 --> <task:annotation-driven executor="xmlExecutor"/> <!-- id指定線程池產生線程名稱的前綴 --> <task:executor id="xmlExecutor" pool-size="5-25" queue-capacity="100" keep-alive="120" rejection-policy="CALLER_RUNS"/>
有關線程池的拒絕策略,參考下文:
線程池--拒絕策略RejectedExecutionHandler
編寫異步任務(@Async註解指定)
1、編寫普通Java類,並設置方法爲@Async註解
只需要簡單這麼一步即可在執行註解方法時自動由Spring框架執行異步操作。
p
ackage tech.bbwang.springtask.scheduled.demo;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class ScheduledTaskExample {
public ScheduledTaskExample(){
}
@Async
public void printTime(){
System.out.println((new Date()).toString());
}
}
2、線程池
配置線程池
最簡單的形式,只需要在spring配置文件里加一條配置即可。
<task:executor id="xmlExecutor" pool-size="2" />
添加此配置需要在Spring配置文件的<beans>頭部添加下面的約束文件(task相關處的命名空間)
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task" xmlns:context="http://www.springframework.org/schema/context" 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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
使用線程池
線程池xmlExecutor作爲一個Spring的bean存在,可以被注入到需要的地方。
比如:
定義一個使用線程池的類TaskExecutorExample,該類使用線程池跑10個打印當前時間的任務。
package tech.bbwang.springtask.demo;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import tech.bbwang.App;
import java.util.HashMap;
import java.util.Map;
/**
* 任務執行樣例
*/
@Component
public class TaskExecutorExample
{
private TaskExecutor taskExecutor;
public TaskExecutorExample(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void printMessages() {
for(int i = 0; i <10; i++) {
taskExecutor.execute(new Runnable(){
public void run(){
System.out.println((new Date()).toString());
}
});
}
}
}
Spring配置文件設置:
<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="tech.bbwang.springtask.demo"/> <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5" /> <property name="maxPoolSize" value="10" /> <property name="queueCapacity" value="25" /> </bean> <bean id="taskExecutorExample" class="tech.bbwang.springtask.demo.TaskExecutorExample"> <constructor-arg ref="taskExecutor" /> </bean> </beans>
3、定時器和定時任務
定義定時器
spring配置文件:
<!-- pool-size:此參數默認爲1,此時,不同的定時任務不可同時進行,因爲線程數不夠。需要自己設置>1的數值來保證,同一個定時任務前一個未完成情況下不啓動下一個,但不用的定時任務可以同時進行--> <task:scheduler id="taskScheduler" pool-size="10"/>
定義定時任務
spring配置文件:
<task:scheduled-tasks> <!-- 配置定時任務,cron=一秒一次--> <task:scheduled ref="scheduledTaskExample" method="printTime" cron="0/5 * * * * ?"/> <!-- 配置定時任務,cron=每日0時和12時各執行一次任務--> <!--Cron表達式生成器 http://www.pdtools.net/tools/becron.jsp--> <!--<task:scheduled ref="scheduledTaskExample" method="printTime" cron="0/1 0/1 0,12 * * ?"/>--> </task:scheduled-tasks>
有關corn表達式可以參考:
定義定時任務類
package tech.bbwang.springtask.scheduled.demo;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class ScheduledTaskExample {
public ScheduledTaskExample(){
}
@Async
public void printTime(){
System.out.println((new Date()).toString());
}
}
定義運行類
其實已經完全由Spring配置解決了運行問題,只需要給一個運行Spring配置的主函數即可。
package tech.bbwang;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.concurrent.CountDownLatch;
public class SpringAsyncTask {
public static void main( String[] args )
{
new ClassPathXmlApplicationContext("spring-async*.xml");
}
}