Java並發(6)帶返回結果的任務執行


攜帶結果的任務

JDK5提供了有可返回值的任務的執行。java.util.concurrent中Callable與Futrue用以實現帶返回值的任務執行。

使用Callable與Futrue與使用Runnable最大的兩個區別在於:

1、Callable/Future是帶返回值的;Runnable無法帶返回值。

2、Callable/Future所執行的任務是可取消的。Runnable的任務無法取消。

 

Callable接口

Callable 接口類似於 Runnable,兩者都是為那些其實例可能被另一個線程執行的類設計的。可返回值的任務必須實現Callable接口。

public interface Callable<V> {

V call() throws Exception;

}

call()方法用於計算結果,如果無法計算結果,則拋出一個異常。Vcall方法的結果類型。

 

Callable接口定義了一個call方法可以作為線程的執行體,但call方法比run方法更強大:

    call()方法可以有返回值。

    call()方法可以申明拋出異常。

 

通過ExecutorSevicesubmit()方法將Callable提交至線程池中執行,submit()方法返回一個Future實例。

使用CompletionService接口可以用於提交一組Callable任務,其take()方法返回已完成的一個Callable任務對應的Future實例。好比同時種了幾塊地的麥子,然后就等待收割。收割時,則是那塊先成熟了,則先去收割哪塊麥子。

 

 

Futrue接口

Future 表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果。如果為了可取消性而使用 Future 但又不提供可用的結果,則可以聲明 Future<?> 形式類型、並返回 null 作為底層任務的結果。

一旦計算完成,就不能再取消計算。

提交(submit()方法)Callable任務,可以獲取一個Future實例。Futrue實例調用get()方法即可獲取Callable任務返回值。

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;

}

 

Future接口里定義了如下幾個公共方法控制他關聯的Callable任務:

V get():返回Callable任務里的call()方法的返回值,調用該方法將導致線程阻塞,必須等到子線程結束才得到返回值。

V get(long timeout,TimeUnit unit) : 返回Callable任務里的call方法的返回值。該方法讓程序最多阻塞timeoutunit指定的時間。如果經過指定時間后Callable任務依然沒有返回值,將會拋出TimeoutException

boolean cancel(boolean mayInterruptlfRunning) :試圖取消該Future里關聯的Callable任務。

boolean isCancelled() :如果在Callable任務正常完成前被取消,則返回true

boolean isDone() :如果Callable任務已經完成,則返回true

 

 

例:使用Executor框架執行Callable並返回結果。

import java.util.concurrent.Executors;

import java.util.concurrent.ExecutorService;

 

import java.util.concurrent.*;

 

public class Test {

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

        // 創建一個線程池

        ExecutorService pool = Executors.newFixedThreadPool(2);

        // 創建兩個有返回值的任務

        Callable c1 = new MyCallable("A");

        Callable c2 = new MyCallable("B");

        // 執行任務並獲取Future對象

        Future f1 = pool.submit(c1);

        Future f2 = pool.submit(c2);

        // Future對象上獲取任務的返回值,並輸出到控制台

        System.out.println(">>>" + f1.get().toString());

        System.out.println(">>>" + f2.get().toString());

        // 關閉線程池

        pool.shutdown();

    }

}

 

class MyCallable implements Callable {

    private String oid;

 

    MyCallable(String oid) {

        this.oid = oid;

    }

 

    @Override

    public Object call() throws Exception {

        return oid + "任務返回的內容";

    }

}

 

 

執行輸出結果:

>>>A任務返回的內容

>>>B任務返回的內容

 

 

RunnableFuture接口

public interface RunnableFuture<V> extends Runnable, Future<V> {

void run();

}

FutrueTask類

java.util.concurrent.FutureTask<V>

Future接口的一個實現類。該實現類實現Future接口,並實現了Runnable接口。FutureTask即可以作為Threadtarget

 

使用FutrueTask執行單個任務。

創建、並啟動有返回值的線程的步驟如下:

1.創建Callable接口的實現類,實現call方法。

2.創建Callable實現類的實例,使用FutureTask類來包裝Callable對象。

3.使用FutureTask對象作為Thread對象的target創建、並啟動新線程。

4.調用FutureTask對象的方法來獲得子線程執行結束后的返回值。

 

例:使用FutrueTask類執行Callable並返回結果。

class RtnThread implements Callable<Integer> {

    public Integer call() {

        // 執行過程

    }

}

 

public class CallableTest {

    public static main(String[] args) {

        // 創建Callable對象。

        RtnThread rt = new RtnThread();

        FutureTask<Integer> task = new FutureTask<Integer>(rt);

        // ..

        // 創建線程,並啟動。

        new Thread(task).start();

        // ..

        Integer i = task.get(); // 獲取線程返回值。

    }

}

創建Callable實現類與創建Runnable實現類並沒有太大差別,只是Callablecall允許拋出異常,而且允許帶返回值。

 


免責聲明!

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



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