【Java併發編程學習 8】Callable和Future詳解

Callable和Future

什麼是Callable

在Java中,創建線程一般有兩種方式,一種是繼承Thread類,一種是實現Runnable接口。然而,這兩種方式的缺點是在線程任務執行結束後,無法獲取執行結果。我們一般只能採用共享變量或共享存儲區以及線程通信的方式實現獲得任務結果的目的。

不過,Java中,也提供了使用Callable和Future來實現獲取任務結果的操作。Callable用來執行任務,產生結果,而Future用來獲得結果。

Callable和Runnable源碼對比

Callable接口與Runnable接口是否相似,查看源碼::
在這裏插入圖片描述在這裏插入圖片描述
區別:
Runnable接口,在它裏面只聲明瞭一個run()方法:
由於run()方法返回值爲void類型,所以在執行完任務之後無法返回任何結果。

Callable接口,在它裏面也只聲明瞭一個方法,只不過這個方法叫做call():
可以看到,這是一個Callable是一個泛型接口,call()函數返回的類型就是傳遞進來的V類型。

Callable如何使用

一般情況下是配合ExecutorService來使用的,在ExecutorService接口中聲明瞭若干個submit方法的重載版本:(ExecutorService就是線程池的實現類,上篇章文講解了詳細的線程池):
在這裏插入圖片描述

看到返回值了嗎,返回值都是Future泛型接口

什麼是Future

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

三者代碼示例:

package com.lijie;

import java.util.concurrent.*;

public class TestMain {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //創建線程池
        ExecutorService executor = Executors.newCachedThreadPool();

        //給線程池添加Callable線程,並且執行線程,獲取線程執行結果
        Future<Integer> future = executor.submit(new TestCallable());

        //get方法獲取異步執行的結果,如果沒有結果可用,此方法會阻塞直到異步計算完成。
        Integer integer = future.get();
        System.out.println("子線程執行結果"+integer);

        // 關閉線程池
        if (executor != null) {
            executor.shutdown();
        }

        //主線程執行
        for (int i = 0; i < 10; i++)
            System.out.println("主線程執行:i==" + i);

    }

}

//實現Callable接口
class TestCallable implements Callable<Integer> {

    public Integer call() throws Exception {
        System.out.println("執行線程");
        Thread.sleep(5000);
        return 5000;
    }

}

Future常用獲取結果方法

  1. V get() :獲取異步執行的結果,如果沒有結果可用,此方法會阻塞直到異步計算完成。
  2. V get(Long timeout , TimeUnit unit) :獲取異步執行結果,如果沒有結果可用,此方法會阻塞,但是會有時間限制,如果阻塞時間超過設定的timeout時間,該方法將拋出異常。
  3. boolean isDone() :如果任務執行結束,無論是正常結束或是中途取消還是發生異常,都返回true。
  4. boolean isCanceller() :如果任務完成前被取消,則返回true。
  5. boolean cancel(boolean mayInterruptRunning) :其實就是關閉線程執行的任務:能夠中斷執行中的任務、判斷任務是否執行完成、獲取任務執行完成後額結果。
    5.1 如果任務還沒開始,執行cancel(…)方法將返回false;
    5.2如果任務已經啓動,執行cancel(true)方法將以中斷執行此任務線程的方式來試圖停止任務,如果停止成功,返回true;
    5.3當任務已經啓動,執行cancel(false)方法將不會對正在執行的任務線程產生影響(讓線程正常執行到完成),此時返回false;
    5.4當任務已經完成,執行cancel(…)方法將返回false。
    5.5mayInterruptRunning參數表示是否中斷執行中的線程。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章