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

一. Callable接口與Runnable接口區別

建立java線程,咱們常用兩種方式:java

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

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

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());
}
相關文章
相關標籤/搜索