多線程(Multithreading)是Java的一個特性,它能夠容許一個程序的多個部分(也就是線程)併發地執行,以達到最大程度利用CPU的目的。html
關於多線程編程(Multithread Programming),下面介紹一下Future
的特性和基本用法。java
Future
(java.util.concurrent Interface Future<V>
)表示異步計算的結果。Future
接口提供了檢查計算是否完成、檢查計算是否被取消、等待計算完成並獲取計算結果等方法。git
A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled. If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task.github
下面對Future
的幾個方法作一下簡要介紹並提供代碼演示。api
private static ExecutorService executor = Executors.newSingleThreadExecutor();
public static Future<Integer> calculate(Integer input) {
return executor.submit(() -> {
Thread.sleep(3000);
return input * input;
});
}
複製代碼
get()
V get() Waits if necessary for the computation to complete, and then retrieves its result. 複製代碼
get()
方法用戶返回計算結果,若是計算尚未完成,則在get的時候會進行阻塞,直到獲取到結果爲止。bash
get()
Sample ExampleFuture<Integer> calculateFuture = calculate(100);
System.out.println("calculate result: "+calculateFuture.get());
複製代碼
在阻塞3s之後,能夠獲得執行結果:多線程
calculate result: 10000
複製代碼
get(long timeout, TimeUnit unit)
V get(long timeout, TimeUnit unit) Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if available. 複製代碼
get(long timeout, TimeUnit unit)
方法的耐心是有限的,若是在指定時間內沒有完成計算,則會拋出TimeoutException
.併發
get(long timeout, TimeUnit unit)
Sample ExampleFuture<Integer> calculateFuture = calculate(100);
System.out.println(calculateFuture.get(2, TimeUnit.SECONDS));
複製代碼
等待2s之後,拋出異常:oracle
Exception in thread "main" java.util.concurrent.TimeoutException
複製代碼
isDone()
boolean isDone() Returns true if this task completed. 複製代碼
isDone()
方法用於判斷當前Future是否執行完成。
isDone()
Sample ExampleFuture<Integer> calculateFuture = calculate(100);
System.out.println(calculateFuture.isDone());
while (!calculateFuture.isDone()){ }
System.out.println(calculateFuture.isDone());
複製代碼
首先輸出false
,循環3秒之後輸出true
。
cancel(boolean mayInterruptIfRunning)
boolean cancel(boolean mayInterruptIfRunning) Attempts to cancel execution of this task. 複製代碼
取消當前線程的執行。參數表示是否在線程執行的過程當中阻斷。
isCancelled()
boolean isCancelled() Returns true if this task was cancelled before it completed normally. 複製代碼
判斷當前task是否被取消。
isCancelled()
Sample ExampleFuture<Integer> calculateFuture = calculate(100);
System.out.println("isCancelled = "+calculateFuture.isCancelled());
System.out.println("cancel success = "+calculateFuture.cancel(true));
System.out.println("isCancelled = "+calculateFuture.isCancelled());
複製代碼
下面提供一個經過線程池來異步獲取執行結果並彙總的代碼示例。
Callable<Long> callable = new Callable<Long>() {
@Override
public Long call() throws Exception {
long start = System.currentTimeMillis();
Thread.sleep(100);
long end = System.currentTimeMillis();
long seed = end - start;
System.out.println("seed=" + seed);
return seed;
}
};
List<Callable<Long>> tasks = new ArrayList<>();
tasks.add(callable);
tasks.add(callable);
tasks.add(callable);
tasks.add(callable);
tasks.add(callable);
tasks.add(callable);
tasks.add(callable);
tasks.add(callable);
tasks.add(callable);
tasks.add(callable);
int poolSize = Runtime.getRuntime().availableProcessors();
System.out.println("poolSize=" + poolSize);
ExecutorService executorService = Executors.newFixedThreadPool(poolSize);
List<Future<Long>> futures = executorService.invokeAll(tasks);
long result = 0;
for (Future<Long> future : futures) {
result += future.get();
}
System.out.println("result=" + result);
executorService.shutdown();
複製代碼
運行程序的主機是8核的,所以啓動了8個線程,每次會同時執行8個task。
下面是運行結果:
poolSize=8
seed=109
seed=109
seed=109
seed=109
seed=109
seed=109
seed=109
seed=109
seed=110
seed=110
result=1092
複製代碼