Java執行緒池的實現--Executor、ThreadPoolTaskExecutor、@Async的使用
阿新 • • 發佈:2018-11-21
一、為什麼要使用執行緒池
當我們需要的併發執行執行緒數量很多時,且每個執行緒執行很短的時間就結束了,這樣,我們
頻繁的建立、銷燬執行緒
就大大降低了工作效率(建立和銷燬執行緒需要時間、資源)。java中的執行緒池可以達到這樣的效果:一個執行緒執行完任務之後,繼續去執行下一個任務,不被銷燬,這樣執行緒利用率提高了。
二、Jdk 1.5後執行緒池
//【固定的執行緒池】定義程序池並指定其大小
ExecutorService threadPool = Executors.newFixedThreadPool(3);
for(int i=1;i<=10 ;i++){
final int task = i;
threadPool.execute(new Runnable(){
@Override
public void run() {
for(int j=1;j<=2;j++){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + task);
}
}
});
}
java.util.concurrent.Executor
介面表示執行緒池,它的execute(Runnable task)
用來執行Runnable
型別的任務。Executor的子介面ExecutorService
中聲明瞭管理執行緒池的一些方法,比如關閉執行緒池的shutdown()
等。Executors
類中包含了一些靜態方法,生成各種型別的執行緒池ExecutorService例項
。
三、Spring非同步執行緒池
非同步呼叫
在解釋非同步呼叫之前,我們先來看同步呼叫的定義;同步就是整個處理過程順序執行,當各個過程都執行完畢,並返回結果。 非同步呼叫則是隻是傳送了呼叫的指令,呼叫者無需等待被呼叫的方法完全執行完畢;而是繼續執行下面的流程。
1、TaskExecutor
TaskExecutor是Spring非同步執行緒池的介面類,其實質是java.util.concurrent.Executor。
Spring 已經實現的異常執行緒池:
SimpleAsyncTaskExecutor
:不是真的執行緒池,每次呼叫都會建立一個新的執行緒。SyncTaskExecutor
:這個類沒有實現非同步呼叫,只是一個同步操作。只適用於不需要多執行緒的地方。ConcurrentTaskExecutor
:Executor的適配類,不推薦使用。如果ThreadPoolTaskExecutor不滿足要求時,才用考慮使用這個類。SimpleThreadPoolTaskExecutor
:是Quartz的SimpleThreadPool的類。執行緒池同時被quartz和非quartz使用,才需要使用此類。ThreadPoolTaskExecutor
:最常使用,推薦。 其實質是對java.util.concurrent.ThreadPoolExecutor的包裝。
ThreadPoolTaskExecutor的使用:
//spring.xml配置
<!-- 非同步執行緒池 -->
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<!-- 核心執行緒數,執行緒池裡最小執行緒數 -->
<property name="corePoolSize" value="10" />
<!-- 最大執行緒數 -->
<property name="maxPoolSize" value="100" />
<!-- 佇列最大長度 -->
<property name="queueCapacity" value="1000" />
<!-- 執行緒池維護執行緒所允許的空閒時間 -->
<property name="keepAliveSeconds" value="300" />
<!-- 執行緒池對拒絕任務(無執行緒可用)的處理策略 -->
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
</property>
</bean>
//從池中獲取執行緒執行任務
public class ThreadPoolTest {
@Autowired
private TaskExecutor taskExecutor;// 執行緒池
// 將建立的執行緒新增到執行緒池中
public void test() throws Exception {
for (int i = 0; i < 10; i++) {
this.taskExecutor.execute(new AppContentDataPushThread());
}
}
class AppContentDataPushThread implements Runnable {
public AppContentDataPushThread() {
}
@Override
public void run() {
System.out.println("執行執行緒");
}
}
}
2、@Async
2.1、在Spring中啟用@Async
基於註解配置
@Configuration
@EnableAsync
public class SpringAsyncConfig { ... }
基於xml配置
<task:executor id="myexecutor"pool-size="5"/>
<task:annotation-driven executor="myexecutor"/>
2.2、使用
@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;
}
}
//呼叫
asyncDemo.asyncInvokeSimplest();
asyncDemo.asyncInvokeWithException("test");
Future<String> future = asyncDemo.asyncInvokeReturnFuture(100);
System.out.println(future.get());