簡單理解Callable接口


Callable接口:

  Callable,新啟線程的一種方式,返回結果並且可能拋出異常的任務,在前面的新啟線程的文章中用過,但是沒有具體講解

  優點:

    可以獲取線程的執行結果,也稱為返回值

    通過與Future的結合,可以實現利用Future來跟蹤異步計算的結果

Runnable和Callable的區別:

  Callable規定的方法是call(),Runnable規定的接口是run();

  Callable的任務執行后可返回值,而Runnable的任務是不能有返回值的;

  call方法可以拋出異常,run方法不可以

  運行Callable任務可以拿到一個Future對象,表示異步計算的結果,它提供了檢查是否計算完成的方法,以等待計算的完成,並檢索計算的結果,通過Future對象可以了解任務執行情況,可以取消任務的執行,還可以獲取執行結果

Future接口:

  Future是一個接口,代表了一個異步計算的結果,接口中的方法用來檢查計算是否完成,等待完成和得到計算結果;

  當計算完成后,只能通過get()方法得到結果,get()方法會阻塞,一直到線程的計算結果完成並返回;

  如果想取消,那么調用cancel()方法,其他方法用於確定任務是正常完成還是取消了;

  一旦計算完成了,那么這個計算就不能被取消

FutureTask類:

  FutureTask類實現了RunnableFuture接口,而RunnableFuture接口是繼承了Runnable和Future接口,所以說FutureTask是一個提供異步計算結果的任務;

  FutureTask可以用來包裝Callable或者Runnable接口的實現對象,因為FutureTask實現了Runnable接口,所以FutureTask也可以提交給線程池

Callable,Future,FutureTask三者之間的關系:

 

 

Callable的兩種執行方式:

1:借助FutureTask,包裝Callable接口的實現類,然后傳遞給Thread線程執行

 

package org.dance.day2.future;

import org.dance.tools.SleepTools;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * Callable的兩種執行方式
 * @author ZYGisComputer
 */
public class UseCallable {

    /**
     * 實現Callable接口的線程
     */
    private static class UseCall implements Callable<Integer>{

        private int sum;

        @Override
        public Integer call() throws Exception {
            System.out.println("callable子線程開始執行任務計算");
            Thread.sleep(2000);
            for (int i = 0; i < 5000; i++) {
                sum += i;
            }
            System.out.println("子線程任務計算完成,返回值:"+sum);
            return sum;
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        UseCall useCall = new UseCall();

        // 使用FutureTask包裝
        FutureTask<Integer> futureTask = new FutureTask<>(useCall);

        // 包裝為Thread
        Thread thread = new Thread(futureTask);

        thread.start();

        // 開始主線程的任務
        Random random = new Random();

        SleepTools.second(1);

        if(random.nextBoolean()){
            System.out.println("獲取Callable result:"+futureTask.get());
        }else{
            System.out.println("中斷計算");
            // 中斷計算,取消線程的執行
            futureTask.cancel(true);
        }
    }

}

2:借助線程池來執行

UseCall useCall = new UseCall();
 // 創建一個線程池
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = executorService.submit(useCall);

線程池這個只粘貼關鍵代碼,線程池的知識就不在這多說了,之后會具體講解

返回的Future接口的使用和FutureTask是一樣的

這個接口實現的線程,是有返回值的

可以說一下我之前用到的場景

是這樣的,我之前用到的一般是用於雲上,或者存儲服務器下載電子文件,就是本身我一個接口就是需要查詢數據庫並,進行結果的大量計算和結果轉換的,同時還要上雲上下載比較大的電子文件,所以我采用Callable配合線程池來完成雲上文件的下載;

作者:彼岸舞

時間:2020\10\04

內容關於:並發編程

本文來源於網絡,只做技術分享,一概不負任何責任


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM