天天看點

Java多線程 Callable和FutureJava多線程 Callable和Future

Java多線程 Callable和Future

文章目錄

  • Java多線程 Callable和Future
    • 1、簡介
    • 2、使用

1、簡介

(1)先來了解一下Callable 接口

Callable是類似于Runnable的接口,實作Callable接口的類和實作Runnable的類都是可被其他線程執行的任務。Callable接口的定義如下:

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}
           

Callable的類型參數是傳回值的類型。例如:

Callable<Integer>表示一個最終傳回Integer對象的異步計算。
           

(2)Future儲存異步計算的結果。實際應用中可以啟動一個計算,将Future對象交給某個線程,然後執行其他操作。Future對象的所有者在結果計算好之後就可以獲得它。Future接口具有下面的方法:

public interface Future<V> {

   //可以用cancel方法取消該計算。如果計算還沒有開始,它被取消且不再開始。
   //如果計算處于運作之中,那麼如果mayInterrupt參數為true,它就被中斷
    boolean cancel(boolean mayInterruptIfRunning);
    
    //判斷是夠被取消
    boolean isCancelled();
    
    //如果計算還在進行,isDone方法傳回false;如果完成了,則傳回true。
    boolean isDone();
    
    //調用被阻塞,直到計算完成
    V get() throws InterruptedException, ExecutionException;
    
    //設定等待時間,get方法的調用逾時,抛出一個TimeoutException異常
    V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
           

(3) FutureTask包裝器是一種非常便利的機制,同時實作了Future和Runnable接口。FutureTask有2個構造方法

public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}
           

建立線程的步驟一般如下:

(1)建立Callable接口的實作類,并實作call()方法,然後建立該實作類的執行個體;

(2)使用FutureTask類來包裝Callable對象,該FutureTask對象封裝了Callable對象的call()方法的傳回值

(3)使用FutureTask對象作為Thread對象的target建立并啟動線程(因為FutureTask實作了Runnable接口)

(4)調用FutureTask對象的get()方法來獲得子線程執行結束後的傳回值。

2、使用

執行個體:

package callableTest;

import java.util.concurrent.*;
/**
* Callable與Future的應用
* Future取得的結果類型和Callable傳回的結果類型必須一緻,這是通過泛型來實作。
* Callable要采用ExecutorService的submit方法送出,傳回的future對象可以取消  * 任務。
* CompletionService用于送出一組Callable任務,其take方法傳回已完成的一個*Callable任務對應的Future對象。
*
**/
public class CallableTest {
    public static void main(String args[]) throws InterruptedException, ExecutionException {

        ExecutorService service = Executors.newSingleThreadExecutor();
        Future<String> future = service.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "hello world";
            }
        });
         System.out.println("等待結果中");
         System.out.println("得到的結果為:" + future.get());

        ExecutorService service2 = Executors.newFixedThreadPool(10);
        CompletionService<Integer> completionService = new ExecutorCompletionService<>(service2);
        for(int i = 0; i < 10; ++i){
            final int temp = i;
            completionService.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    return temp;
                }
            });
        }
        for(int i = 0; i < 10; ++i){
            System.out.println(completionService.take().get());
        }
        service.shutdown();
        service2.shutdown();
    }
}

           

結果:

等待結果中
得到的結果為:hello world
0
1
2
3
4
5
6
7
8
9