在Java中進(jìn)行并行編程最常用的方式是繼承Thread類(lèi)或者實(shí)現(xiàn)Runnable接口。這兩種方式的缺點(diǎn)是在任務(wù)完成后無(wú)法直接獲取執(zhí)行結(jié)果,必須通過(guò)共享變量或線(xiàn)程間通信,使用起來(lái)很不方便。
從Java1.5開(kāi)始提供了Callable和Future兩個(gè)接口,通過(guò)使用它們可以在任務(wù)執(zhí)行完畢后得到執(zhí)行結(jié)果。
下面我們來(lái)學(xué)習(xí)下如何使用Callable、Future和FutureTask。
Callable接口
Callable接口位于java.util.concurrent包,這是一個(gè)泛型接口,里面只聲明了一個(gè)call()方法:
1
2
3
|
public interface Callable<T> { T call() throws Exception; } |
一般配合ExecutorService接口來(lái)使用它,在ExecutorService接口中聲明了幾個(gè)重載的submit方法:
1
2
3
|
<T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); |
第一個(gè)submit方法里面的參數(shù)類(lèi)型就是Callable,另外兩個(gè)本文暫時(shí)不涉及。
Future和FutureTask
Future接口的實(shí)現(xiàn)類(lèi)可以對(duì)Runnable或者Callable的任務(wù)執(zhí)行取消、查詢(xún)、獲取結(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í)行卻沒(méi)有執(zhí)行完畢的任務(wù),如果設(shè)置true,則表示可以取消正在執(zhí)行過(guò)程中的任務(wù) *如果任務(wù)正在執(zhí)行,則返回true *如果任務(wù)還沒(méi)有執(zhí)行,則無(wú)論mayInterruptIfRunning為true還是false,返回true *如果任務(wù)已經(jīng)完成,則無(wú)論mayInterruptIfRunning為true還是false,返回false */ boolean cancel( boolean mayInterruptIfRunning); /** *任務(wù)是否被取消成功,如果在任務(wù)正常完成前被取消成功,則返回 true */ boolean isCancelled(); /** *任務(wù)是否完成 */ boolean isDone(); /** *通過(guò)阻塞獲取執(zhí)行結(jié)果 */ T get() throws InterruptedException, ExecutionException; /** *通過(guò)阻塞獲取執(zhí)行結(jié)果。如果在指定的時(shí)間內(nèi)沒(méi)有返回,則返回null */ T get( long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; } |
總結(jié)下來(lái)Future提供了三種功能:
1
2
3
|
判斷任務(wù)是否完成 能夠中斷任務(wù) 能夠獲取任務(wù)執(zhí)行的結(jié)果 |
JDK中為我們提供了一個(gè)Future接口的實(shí)現(xiàn)類(lèi)FutureTask,它有如下兩個(gè)構(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( "主線(xiàn)程在執(zhí)行任務(wù)..." ); try { Thread.sleep( 2000 ); } catch (InterruptedException ex) { ex.printStackTrace(); } try { System.out.println( "task運(yùn)行結(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( "子線(xiàn)程在執(zhí)行任務(wù)..." ); //模擬任務(wù)耗時(shí) Thread.sleep( 5000 ); return 1000 ; } } |
執(zhí)行結(jié)果:
1
2
3
4
|
子線(xiàn)程在執(zhí)行任務(wù)... 主線(xiàn)程在執(zhí)行任務(wù)... task運(yùn)行結(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( "主線(xiàn)程在執(zhí)行任務(wù)..." ); try { Thread.sleep( 2000 ); } catch (InterruptedException ex) { ex.printStackTrace(); } try { System.out.println( "task運(yùn)行結(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( "子線(xiàn)程在執(zhí)行任務(wù)..." ); //模擬任務(wù)耗時(shí) Thread.sleep( 5000 ); return 1000 ; } } |
執(zhí)行結(jié)果:
1
2
3
4
|
子線(xiàn)程在執(zhí)行任務(wù)... 主線(xiàn)程在執(zhí)行任務(wù)... task運(yùn)行結(jié)果: 1000 所有任務(wù)執(zhí)行完畢 |
總結(jié)
以上就是本文關(guān)于淺談在Java中使用Callable、Future進(jìn)行并行編程的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專(zhuān)題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!
原文鏈接:https://segmentfault.com/a/1190000012291442