合理使用異步線程開發項目能提升一個項目的併發量,減小響應時間。下面就簡單介紹一下異步線程池的使用,參考博客:https://blog.csdn.net/hry2015/article/details/67640534java
spring 對@Async定義異步任務的方法有3種:spring
1.最簡單的異步調用,返回值爲void;併發
2.帶參數的異步調用,異步方法能夠傳入參數;異步
3.異常調用返回Futureasync
代碼以下:ide
package com.hry.spring.async.annotation; import java.util.concurrent.Future; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Component; /** * 異步方法調用 * * @author hry * */ @Component public class AsyncDemo { private static final Logger log = LoggerFactory.getLogger(AsyncDemo.class); /** * 最簡單的異步調用,返回值爲void */ @Async public void asyncInvokeSimplest() { log.info("asyncSimplest"); } /** * 帶參數的異步調用 異步方法能夠傳入參數 * * @param s */ @Async public void asyncInvokeWithParameter(String s) { log.info("asyncInvokeWithParameter, parementer={}", s); } /** * 異常調用返回Future * * @param i * @return */ @Async public Future<String> asyncInvokeReturnFuture(int i) { log.info("asyncInvokeReturnFuture, parementer={}", i); Future<String> future; try { Thread.sleep(1000 * 1); future = new AsyncResult<String>("success:" + i); } catch (InterruptedException e) { future = new AsyncResult<String>("error"); } return future; } }
spring啓動配置的方式有兩種:測試
1.註解;spa
2.XML配置文件.net
咱們先說註解的方式:線程
@EnableAsync註解能夠開啓異步調用功能, public AsyncTaskExecutor taskExecutor() 方法自定義本身的線程池,線程池前綴」Anno-Executor」。若是不定義,則使用系統默認的線程池。代碼以下:
package com.hry.spring.async.annotation;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* 經過@EnableAsync啓動異步方法
* @author hry
*
*/
@SpringBootApplication
@EnableAsync // 啓動異步調用
public class AsyncApplicationWithAnnotation {
private static final Logger log = LoggerFactory.getLogger(AsyncApplicationWithAnnotation.class);
/**
* 自定義異步線程池
* 若是沒有這個方法,則使用默認的線程池
* @return
*/
@Bean
public AsyncTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setThreadNamePrefix("Anno-Executor");//設置線程名稱的前綴
executor.setCorePoolSize(5);//設置核心線程數
executor.setMaxPoolSize(10);//設置最大線程數
// 設置拒絕策略
executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// .....
}
});
// 使用預約義的異常處理類
// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
public static void main(String[] args) {
log.info("Start AsyncApplication.. ");
SpringApplication.run(AsyncApplicationWithAnnotation.class, args);
}
}
如今寫測試類:
package com.hry.spring.async.annotation; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import com.hry.spring.async.annotation.AsyncApplicationWithAnnotation; import com.hry.spring.async.annotation.AsyncDemo; @RunWith(SpringRunner.class) @SpringBootTest(classes=AsyncApplicationWithAnnotation.class) public class AsyncApplicationWithAnnotationTests { @Autowired private AsyncDemo asyncDemo; @Test public void contextLoads() throws InterruptedException, ExecutionException { asyncDemo.asyncInvokeSimplest(); asyncDemo.asyncInvokeWithParameter("test"); Future<String> future = asyncDemo.asyncInvokeReturnFuture(1000); System.out.println(future.get()); } }
啓動測試類,結果以下:
說明啓動異步線程池成功,執行上面的3個方法分別用了3個線程。
再說一下XML配置文件配置的方式:
咱們先建立XML配置文件:
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" 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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd" default-lazy-init="false"> <!-- 等價於 @EnableAsync, executor指定線程池 --> <task:annotation-driven executor="xmlExecutor"/> <!-- id指定線程池產生線程名稱的前綴 --> <task:executor id="xmlExecutor" pool-size="3-20" queue-capacity="100" keep-alive="120" rejection-policy="CALLER_RUNS"/> </beans>
其中id表示線程名稱的前綴,pool-size表示線程池的大小,「3-20」表示線程池的最大線程數爲20,最小線程數爲3,也能夠設置成一個值,如:pool-size=5,則表示線程池的核心線程數和最大線程數相同,都是5。queue-capacity表示排隊隊列的長度。
項目啓動時讀取xml配置文件,以下:
package com.hry.spring.async.xml; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; /** * 經過XML啓動異步 * @author hry * */ @SpringBootApplication @ImportResource("classpath:/async/spring_async.xml") public class AsyncApplicationWithXML { private static final Logger log = LoggerFactory.getLogger(AsyncApplicationWithXML.class); public static void main(String[] args) { log.info("Start AsyncApplication.. "); SpringApplication.run(AsyncApplicationWithXML.class, args); } }
編寫測試類:
package com.hry.spring.async.xml; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(classes=AsyncApplicationWithXML.class) public class AsyncApplicationWithXMLTest { @Autowired private AsyncDemo asyncDemo; @Test public void contextLoads() throws InterruptedException, ExecutionException { asyncDemo.asyncInvokeSimplest(); asyncDemo.asyncInvokeWithParameter("test"); Future<String> future = asyncDemo.asyncInvokeReturnFuture(100); System.out.println(future.get()); } }
測試結果以下:
測試成功。