Callable、FutureTask和Future詳解帶你理解java併發編程

一. Callable接口與Runnable接口區別

創建java線程,我們經常使用兩種方式:

  • 一是直接繼承Thread
  • 另一種是實現Runnable接口

但這兩種方式有一個缺陷:在執行完任務之後無法直接獲取執行結果。

1. 接口定義

1.1 Callable接口

public interface Callable<V> {
    V call() throws Exception;
}

1.2 Runnable接口

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

2. 區別

  • Runnable沒有返回值;Callable可以返回執行結果(泛型)。
  • Runnable異常只能在內部處理,不能往上繼續拋出;Callable接口的call()方法允許拋出異常。
  • Callable需要配合FutureTask或Future使用。

二. Future接口和FutureTask實現類

1. Future接口定義了5個方法

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;
}
  • cancel方法用來取消任務,如果取消任務成功則返回true,如果取消任務失敗則返回false。參數mayInterruptIfRunning表示是否允許取消正在執行卻沒有執行完畢的任務,如果設置true,則表示可以取消正在執行過程中的任務。如果任務已經完成,則無論mayInterruptIfRunning爲true還是false,此方法肯定返回false,即如果取消已經完成的任務會返回false;如果任務正在執行,若mayInterruptIfRunning設置爲true,則返回true,若mayInterruptIfRunning設置爲false,則返回false;如果任務還沒有執行,則無論mayInterruptIfRunning爲true還是false,肯定返回true。
  • isCancelled方法表示任務是否被取消成功,如果在任務正常完成前被取消成功,則返回 true。
  • isDone方法表示任務是否已經完成,若任務完成,則返回true;
  • get()方法用來獲取執行結果,這個方法會產生阻塞,會一直等到任務執行完畢才返回;
  • get(long timeout, TimeUnit unit)用來獲取執行結果,如果在指定時間內,還沒獲取到結果,就直接返回null。

2. FutureTask實現了RunnableFuture接口,RunnableFuture繼承了Runnable接口和Future接口

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

三. 基本用法舉例

1. Runnable

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("線程執行中...");
    }
};
Thread thread = new Thread(runnable);
thread.start();

2. Callable

2.1 FutureTask

Callable < Integer > callable = new Callable < Integer > () {
    @Override
    public Integer call() throws Exception {
        System.out.println("線程執行中...");
        return 100;
    }
};
FutureTask < Integer > futureTask = new FutureTask < Integer > (callable);
new Thread(futureTask).start();
// 等待1秒,讓線程執行
TimeUnit.SECONDS.sleep(1);
if(futureTask.isDone()) {
    System.out.println("獲取執行結果:" + futureTask.get());
}

2.2 Future

Callable < Integer > callable = new Callable < Integer > () {
    @Override
    public Integer call() throws Exception {
        System.out.println("線程執行中...");
        return 100;
    }
};
ExecutorService service = Executors.newCachedThreadPool();
Future < Integer > future = service.submit(callable);
// 等待1秒,讓線程執行
TimeUnit.SECONDS.sleep(1);
if(futureTask.isDone()) {
    System.out.println("獲取執行結果:" + future.get());
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章