Future與FutureTask接口實現(xiàn)示例詳解
正文
Future就是對于具體的Runnable或者Callable任務(wù)的執(zhí)行結(jié)果進(jìn)行取消、查詢是否完成、獲取結(jié)果等操作。必要時可以通過get方法獲取執(zhí)行結(jié)果,該方法會阻塞直到任務(wù)返回結(jié)果。
Future類
Future類位于java.util.concurrent包下,它是一個接口:
/** * @see FutureTask * @see Executor * @since 1.5 * @author Doug Lea * @param <V> The result type returned by this Future's <tt>get</tt> method */ public interface Future<V> { /** * Attempts to cancel execution of this task. This attempt will * fail if the task has already completed, has already been cancelled, * or could not be cancelled for some other reason. If successful, * and this task has not started when <tt>cancel</tt> is called, * this task should never run. If the task has already started, * then the <tt>mayInterruptIfRunning</tt> parameter determines * whether the thread executing this task should be interrupted in * an attempt to stop the task. * */ boolean cancel(boolean mayInterruptIfRunning); /** * Returns <tt>true</tt> if this task was cancelled before it completed * normally. */ boolean isCancelled(); /** * Returns <tt>true</tt> if this task completed. * */ boolean isDone(); /** * Waits if necessary for the computation to complete, and then * retrieves its result. * * @return the computed result */ V get() throws InterruptedException, ExecutionException; /** * Waits if necessary for at most the given time for the computation * to complete, and then retrieves its result, if available. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return the computed result */ V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
在Future接口中聲明了5個方法,下面依次解釋每個方法的作用:
cancel()方法用來取消任務(wù),如果取消任務(wù)成功則返回true,如果取消任務(wù)失敗則返回false。參數(shù)mayInterruptIfRunning表示是否允許取消正在執(zhí)行卻沒有執(zhí)行完畢的任務(wù),如果設(shè)置true,則表示可以取消正在執(zhí)行過程中的任務(wù)。如果任務(wù)已經(jīng)完成,則無論mayInterruptIfRunning為true還是false,此方法肯定返回false,即如果取消已經(jīng)完成的任務(wù)會返回false;如果任務(wù)正在執(zhí)行,若mayInterruptIfRunning設(shè)置為true,則返回true,若mayInterruptIfRunning設(shè)置為false,則返回false;如果任務(wù)還沒有執(zhí)行,則無論mayInterruptIfRunning為true還是false,肯定返回true。
isCancelled()方法表示任務(wù)是否被取消成功,如果在任務(wù)正常完成前被取消成功,則返回 true。
isDone()方法表示任務(wù)是否已經(jīng)完成,若任務(wù)完成,則返回true;
get()方法用來獲取執(zhí)行結(jié)果,這個方法會產(chǎn)生阻塞,會一直等到任務(wù)執(zhí)行完畢才返回;
get(long timeout, TimeUnit unit)用來獲取執(zhí)行結(jié)果,如果在指定時間內(nèi),還沒獲取到結(jié)果,就直接返回null。
也就是說Future提供了三種功能:
- 1)判斷任務(wù)是否完成;
- 2)能夠中斷任務(wù);
- 3)能夠獲取任務(wù)執(zhí)行結(jié)果。
因為Future只是一個接口,所以是無法直接用來創(chuàng)建對象使用的,因此就有了下面的FutureTask。
FutureTask
FutureTask的實現(xiàn):
public class FutureTask<V> implements RunnableFuture<V>
FutureTask類實現(xiàn)了RunnableFuture接口,RunnableFuture接口:
public interface RunnableFuture<V> extends Runnable, Future<V> { /** * Sets this Future to the result of its computation * unless it has been cancelled. */ void run(); }
可以看出RunnableFuture繼承了Runnable接口和Future接口,而FutureTask實現(xiàn)了RunnableFuture接口。所以它既可以作為Runnable被線程執(zhí)行,又可以作為Future得到Callable的返回值。
FutureTask提供了2個構(gòu)造器:
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable } public FutureTask(Runnable runnable, V result) { this.callable = Executors.callable(runnable, result); this.state = NEW; // ensure visibility of callable }
可以看到,Runnable注入會被Executors.callable()函數(shù)轉(zhuǎn)換為Callable類型,即FutureTask最終都是執(zhí)行Callable類型的任務(wù)。該適配函數(shù)的實現(xiàn)如下:
public static <T> Callable<T> callable(Runnable task, T result) { if (task == null) throw new NullPointerException(); return new RunnableAdapter<T>(task, result); }
RunnableAdapter適配器
/** * A callable that runs given task and returns given result */ static final class RunnableAdapter<T> implements Callable<T> { final Runnable task; final T result; RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } public T call() { task.run(); return result; } }
FutureTask是Future接口的一個唯一實現(xiàn)類。
FutureTask實現(xiàn)了Runnable,因此它既可以通過Thread包裝來直接執(zhí)行,也可以提交給ExecuteService來執(zhí)行。
FutureTask實現(xiàn)了Futrue可以直接通過get()函數(shù)獲取執(zhí)行結(jié)果,該函數(shù)會阻塞,直到結(jié)果返回。
實例:
Callable+Future獲取執(zhí)行結(jié)果
public class Test { public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool(); Task task = new Task(); Future<Integer> result = executor.submit(task); executor.shutdown(); try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("主線程在執(zhí)行任務(wù)"); try { System.out.println("task運(yùn)行結(jié)果"+result.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("所有任務(wù)執(zhí)行完畢"); } } class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("子線程在進(jìn)行計算"); Thread.sleep(3000); int sum = 0; for(int i=0;i<100;i++) sum += i; return sum; } }
執(zhí)行結(jié)果:
子線程在進(jìn)行計算
主線程在執(zhí)行任務(wù)
task運(yùn)行結(jié)果4950
所有任務(wù)執(zhí)行完畢
Callable+FutureTask獲取執(zhí)行結(jié)果
public class Test { public static void main(String[] args) { //第一種方式 ExecutorService executor = Executors.newCachedThreadPool(); Task task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); executor.submit(futureTask); executor.shutdown(); //第二種方式,注意這種方式和第一種方式效果是類似的,只不過一個使用的是ExecutorService,一個使用的是Thread /*Task task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); Thread thread = new Thread(futureTask); thread.start();*/ try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("主線程在執(zhí)行任務(wù)"); try { System.out.println("task運(yùn)行結(jié)果"+futureTask.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("所有任務(wù)執(zhí)行完畢"); } } class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("子線程在進(jìn)行計算"); Thread.sleep(3000); int sum = 0; for(int i=0;i<100;i++) sum += i; return sum; } }
以上就是Future與FutureTask接口實現(xiàn)示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Future FutureTask接口實現(xiàn)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
spring boot整合mybatis+mybatis-plus的示例代碼
這篇文章主要介紹了spring boot整合mybatis+mybatis-plus的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01SpringBoot項目打包成jar后獲取classpath下文件失敗的解決
這篇文章主要介紹了SpringBoot項目打包成jar后獲取classpath下文件失敗的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07一篇文章帶你了解Java容器,面板及四大布局管理器應(yīng)用
這篇文章主要介紹了JAVA布局管理器與面板組合代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2021-08-08關(guān)于Spring的AnnotationAwareAspectJAutoProxyCreator類解析
這篇文章主要介紹了關(guān)于Spring的AnnotationAwareAspectJAutoProxyCreator類解析,Spring是一個開源免費(fèi)的框架 , 容器,是一個輕量級的框架 ,需要的朋友可以參考下2023-05-05Scala數(shù)據(jù)庫連接池的簡單實現(xiàn)
本文主要介紹了Scala數(shù)據(jù)庫連接池的簡單實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02關(guān)于Java三大特性之多態(tài)的總結(jié)
這篇文章主要介紹了關(guān)于Java三大特性之多態(tài)的總結(jié),內(nèi)容詳細(xì),涉及多態(tài)的定義,存在條件,好處,分類及實現(xiàn)方式等相關(guān)內(nèi)容,具有一定參考價值,需要的朋友可以了解下。2017-11-11java字符串?dāng)?shù)組進(jìn)行大小排序的簡單實現(xiàn)
下面小編就為大家?guī)硪黄猨ava字符串?dāng)?shù)組進(jìn)行大小排序的簡單實現(xiàn)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09