在Java中進行并行編程最常用的方式是繼承Thread類或者實現(xiàn)Runnable接口。這兩種方式的缺點是在任務(wù)完成后無法直接獲取執(zhí)行結(jié)果,必須通過共享變量或線程間通信,使用起來很不方便。
從Java1.5開始提供了Callable和Future兩個接口,通過使用它們可以在任務(wù)執(zhí)行完畢后得到執(zhí)行結(jié)果。
下面我們來學(xué)習(xí)下如何使用Callable、Future和FutureTask。
Callable接口
Callable接口位于java.util.concurrent包,這是一個泛型接口,里面只聲明了一個call()方法:
1
2
3
|
public interface Callable<T> { T call() throws Exception; } |
一般配合ExecutorService接口來使用它,在ExecutorService接口中聲明了幾個重載的submit方法:
1
2
3
|
<T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); |
第一個submit方法里面的參數(shù)類型就是Callable,另外兩個本文暫時不涉及。
Future和FutureTask
Future接口的實現(xiàn)類可以對Runnable或者Callable的任務(wù)執(zhí)行取消、查詢、獲取結(jié)果的操作。
Future接口也位于java.util.concurrent包下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public interface Future<T> { /** *取消任務(wù) *@param mayInterruptIfRunning *是否允許取消正在執(zhí)行卻沒有執(zhí)行完畢的任務(wù),如果設(shè)置true,則表示可以取消正在執(zhí)行過程中的任務(wù) *如果任務(wù)正在執(zhí)行,則返回true *如果任務(wù)還沒有執(zhí)行,則無論mayInterruptIfRunning為true還是false,返回true *如果任務(wù)已經(jīng)完成,則無論mayInterruptIfRunning為true還是false,返回false */ boolean cancel( boolean mayInterruptIfRunning); /** *任務(wù)是否被取消成功,如果在任務(wù)正常完成前被取消成功,則返回 true */ boolean isCancelled(); /** *任務(wù)是否完成 */ boolean isDone(); /** *通過阻塞獲取執(zhí)行結(jié)果 */ T get() throws InterruptedException, ExecutionException; /** *通過阻塞獲取執(zhí)行結(jié)果。如果在指定的時間內(nèi)沒有返回,則返回null */ T get( long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; } |
總結(jié)下來Future提供了三種功能:
1
2
3
|
判斷任務(wù)是否完成 能夠中斷任務(wù) 能夠獲取任務(wù)執(zhí)行的結(jié)果 |
JDK中為我們提供了一個Future接口的實現(xiàn)類FutureTask,它有如下兩個構(gòu)造函數(shù)。
1
2
3
4
|
public FutureTask(Callable<T> callable) { } public FutureTask(Runnable runnable, T result) { } |
示例代碼
使用Callable、Future
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
import java.util.concurrent.*; public class Test { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); Task task = new Task(); Future<Integer> future = executorService.submit(task); executorService.shutdown(); System.out.println( "主線程在執(zhí)行任務(wù)..." ); try { Thread.sleep( 2000 ); } catch (InterruptedException ex) { ex.printStackTrace(); } try { System.out.println( "task運行結(jié)果:" +future.get()); } catch (InterruptedException ex) { ex.printStackTrace(); } catch (ExecutionException ex) { ex.printStackTrace(); } System.out.println( "所有任務(wù)執(zhí)行完畢" ); } } class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println( "子線程在執(zhí)行任務(wù)..." ); //模擬任務(wù)耗時 Thread.sleep( 5000 ); return 1000 ; } } |
執(zhí)行結(jié)果:
1
2
3
4
|
子線程在執(zhí)行任務(wù)... 主線程在執(zhí)行任務(wù)... task運行結(jié)果: 1000 所有任務(wù)執(zhí)行完畢 |
使用Callable、FutureTask
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
import java.util.concurrent.*; public class Test { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); Task task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); executorService.submit(futureTask); executorService.shutdown(); System.out.println( "主線程在執(zhí)行任務(wù)..." ); try { Thread.sleep( 2000 ); } catch (InterruptedException ex) { ex.printStackTrace(); } try { System.out.println( "task運行結(jié)果:" +futureTask.get()); } catch (InterruptedException ex) { ex.printStackTrace(); } catch (ExecutionException ex) { ex.printStackTrace(); } System.out.println( "所有任務(wù)執(zhí)行完畢" ); } } class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println( "子線程在執(zhí)行任務(wù)..." ); //模擬任務(wù)耗時 Thread.sleep( 5000 ); return 1000 ; } } |
執(zhí)行結(jié)果:
1
2
3
4
|
子線程在執(zhí)行任務(wù)... 主線程在執(zhí)行任務(wù)... task運行結(jié)果: 1000 所有任務(wù)執(zhí)行完畢 |
總結(jié)
以上就是本文關(guān)于淺談在Java中使用Callable、Future進行并行編程的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
原文鏈接:https://segmentfault.com/a/1190000012291442