Callable、Future、Runnable、FutureTask的聯繫與區別

① Runnable
它是一個接口,在它裏面只聲明瞭一個run()方法:

    public interface Runnable {
        public abstract void run();
    }

由於run()方法返回值爲void類型,所以在執行完任務之後無法返回任何結果。
使用:實現Runnable接口,重寫run()方法。
class RunnableImpl implements Runnable
作爲創建線程的參數:Thread thread = new Thread (Runnable RunnbaleImpl);
作爲要執行的任務提交到線程池:threadPool.submit (Runnable RunnableImpl);
或者是threadPool.execute (Runnable RunnableImpl);
② Callable
是一個接口,在它裏面也只聲明瞭一個方法,只不過這個方法叫做call():

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

call()方法返回泛型V,所以提交Callable接口返回Future接口類,並且會拋出異常。
使用:
A. 定義MyClass實現Callable接口;
class CallabImpl implements Callable
B. 重寫call(),將執行的代碼寫入;
C. 將CallableImpl包裝成FutureTask對象;
FutureTask實現了Runnable和Future接口,可以當作Runnable接口耐心hi用。FutureTask通過在run()內部調用call()來執行任務,並保存了call()的返回值;
FutureTask runnable = new FutureTask(new CallableImpl ());
D. 創建Thread的對象,也可以提交到線程池執行;
Thread thread = new Thread(runnable);//傳入參數Runnable接口
threadPool.submit(runnable);//execute()也可以
E. 此外Callable對象也可以單獨提交到線程池執行;
Future submit(Callable task);
③ Runnable和Callable運用:配合線程池使用
Future submit(Callable task);//多
Future submit(Runnable task, T result);//少
Future<?> submit(Runnable task);//execute()方法也行,只是沒有返回值.
不管是Runnable還是Callable,在提交任務至線程池的過程中會被包裝成RunnableFuture供內部execute()使用。

    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

④ Future
Future就是對於具體的Runnable或者Callable任務的執行結果進行取消、查詢是否完成、獲取結果。必要時可以通過get方法獲取執行結果,該方法會阻塞直到任務返回結果。
比如向線程池提交任務,返回Future.

<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);

Future類位於java.util.concurrent包下,它是一個接口:

    public interface Future<V> {
        boolean cancel(boolean mayInterruptIfRunning);
        boolean isCancelled();
        boolean isDone();
        V get() throws InterruptedException, ExecutionException;
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }

1) cancel方法用來取消任務,如果取消任務成功則返回true,如果取消任務失敗則返回false。參數mayInterruptIfRunning表示是否允許取消正在執行卻沒有執行完畢的任務,如果設置true,則表示可以取消正在執行過程中的任務。
① 如果任務已經完成,則無論mayInterruptIfRunning爲true還是false,此方法肯定返回false,即如果取消已經完成的任務會返回false;
② 如果任務正在執行,若mayInterruptIfRunning設置爲true,則返回true,若mayInterruptIfRunning設置爲false,則返回false;
③ 如果任務還沒有執行,則無論mayInterruptIfRunning爲true還是false,肯定返回true。
2) isCancelled方法表示任務是否被取消成功,如果在任務正常完成前被取消成功,則返回 true。
3) isDone方法表示任務是否已經完成,若任務完成,則返回true;
4) get()方法用來獲取執行結果,這個方法會產生阻塞,會一直等到任務執行完畢才返回;
5) get(long timeout, TimeUnit unit)用來獲取執行結果,如果在指定時間內,還沒獲取到結果,就直接返回null。
總結:Future提供了三種功能:
  1)判斷任務是否完成;
  2)能夠中斷任務;
  3)能夠獲取任務執行結果。
⑤ FutureTask:實現了Runnable和Future接口(後者的唯一實現類)
Future只是一個接口,所以是無法直接用來創建對象使用的,一般是採用它的唯一實現類FutureTask。

public class FutureTask<V> implements RunnableFuture<V>

public interface RunnableFuture<V> extends Runnable, Future<V> {
        void run();
}

可以看出FutureTask實現了RunnableFuture接口,而RunnableFuture繼承了Runnable接口和Future接口。所以它既可以作爲Runnable被線程執行,又可以作爲Future得到Callable的返回值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章