參考鏈接:
java并發(fā)編程-Executor框架+Future
1. 概述
Executor框架是指java 5中引入的一系列并發(fā)庫中與executor相關(guān)的一些功能類,其中包括線程池,Executor,Executors,ExecutorService,CompletionService,F(xiàn)uture,Callable等。他們的關(guān)系為:
- Excutor 執(zhí)行器接口, Executor.execute(Runnalbe) 。Executor在執(zhí)行時使用內(nèi)部的線程池完成操作
- Future<T> 接口,用于獲取異步任務(wù)的執(zhí)行結(jié)果 。核心方法
V get() throws InterruptedException, ExecutionException; 獲取類型為V的執(zhí)行結(jié)果,如果任務(wù)還未產(chǎn)生結(jié)果,阻塞。 - Callable<T> 接口,提供一個返回類型T結(jié)果的 call()的方法
- public interface RunnableFuture<V> extends Runnable, Future<V>{} 一個繼承了Runnable和Future接口的接口(接口可以繼承其他接口,繼承接口的時候可以繼承多個),相當(dāng)于帶有Future功能的線程。
- public class FutureTask<V> implements RunnableFuture<V> 具有一個Callable的成員變量。
2.創(chuàng)建線程池
Executors類,提供了一系列工廠方法用于創(chuàng)先線程池,返回的線程池都實現(xiàn)了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
創(chuàng)建固定數(shù)目線程的線程池。
public static ExecutorService newCachedThreadPool()
創(chuàng)建一個可緩存的線程池,調(diào)用execute
將重用以前構(gòu)造的線程(如果線程可用)。如果現(xiàn)有線程沒有可用的,則創(chuàng)建一個新線程并添加到池中。終止并從緩存中移除那些已有 60 秒鐘未被使用的線程。
public static ExecutorService newSingleThreadExecutor()
創(chuàng)建一個單線程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
創(chuàng)建一個支持定時及周期性的任務(wù)執(zhí)行的線程池,多數(shù)情況下可用來替代Timer類。
3. ExcutorService接口
ExecutorService接口繼承了Executor接口,添加了一些生命周期管理和任務(wù)提交機制的方法。一個Executor的生命周期有三種狀態(tài),運行 ,關(guān)閉 ,終止 。ExecutorService創(chuàng)建時處于運行狀態(tài)。當(dāng)調(diào)用ExecutorService.shutdown()后,處于關(guān)閉狀態(tài),isShutdown()方法返回true。這時,不應(yīng)該再向ExecutorService中添加任務(wù),所有已添加的任務(wù)執(zhí)行完畢后,ExecutorService處于終止?fàn)顟B(tài),isTerminated()返回true。
如果Executor處于關(guān)閉狀態(tài),往Executor提交任務(wù)會拋出unchecked exception RejectedExecutionException。
- 提交任務(wù): <T> Future<T> submit(Callable<T> task);
- 執(zhí)行所有任務(wù):<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
4 一個并發(fā)計算數(shù)組和的實例
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class ConcurrentCalculator {
private ExecutorService exec;
private int cpuCoreNumber;
private List<Future<Long>> tasks = new ArrayList<Future<Long>>();
class SumCalculator implements Callable<Long> {
private int[] nums;
private int start, end;
public SumCalculator(final int[] nums, int start, int end) {
this.nums = nums;
this.start = start;
this.end = end;
}
@Override
public Long call() throws Exception {
long sum = 0l;
for (int i = start; i < end; i++) {
sum += nums[i];
}
return sum;
}
}
public ConcurrentCalculator() {
cpuCoreNumber = Runtime.getRuntime().availableProcessors();
exec = Executors.newFixedThreadPool(cpuCoreNumber);
}
public Long sum(final int[] nums) {
for (int i = 0; i < cpuCoreNumber; i++) {
int increment = nums.length / cpuCoreNumber + 1;
int start = increment * i;
int end = increment * i + increment;
if (end > nums.length) {
end = nums.length;
}
SumCalculator sumCalc = new SumCalculator(nums, start, end);
FutureTask<Long> task = new FutureTask<Long>(sumCalc);
tasks.add(task);
}
return getResult();
}
private Long getResult() {
Long result = 0l;
for (Future<Long> task : tasks) {
try {
Long subSum = task.get();
result += subSum;
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (ExecutionException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
return result;
}
public void close() {
exec.shutdown();
}
}