天天看點

java FutureTask

public class futuretask<v>  extends object  

    implements future<v>, runnable

可見futuretask  是繼承 future  ,産看future源碼得到 public

interface future<v> future  ,在future中有個get方法而擷取結果隻有在計算完成時,否則會一直阻塞直到任務轉入完成狀态,然後會傳回結果或者抛出異常。

future中主要定義了5個方法:

1)boolean cancel(boolean mayinterruptifrunning):試圖取消對此任務的執行。如果任務已完成、或已取消,或者由于某些其他原因而無法取消,則此嘗試将失敗。當調用 cancel 時,如果調用成功,而此任務尚未啟動,則此任務将永不運作。如果任務已經啟動,則 mayinterruptifrunning 參數确定是否應該以試圖停止任務的方式來中斷執行此任務的線程。此方法傳回後,對 isdone() 的後續調用将始終傳回

true。如果此方法傳回 true,則對 iscancelled() 的後續調用将始終傳回 true。 

2)boolean iscancelled():如果在任務正常完成前将其取消,則傳回 true。 

3)boolean isdone():如果任務已完成,則傳回 true。 可能由于正常終止、異常或取消而完成,在所有這些情況中,此方法都将傳回 true。 

4)v get()throws interruptedexception,executionexception:如有必要,等待計算完成,然後擷取其結果。 

5)v get(long timeout,timeunit unit) throws interruptedexception,executionexception,timeoutexception:如有必要,最多等待為使計算完成所給定的時間之後,擷取其結果(如果結果可用)。

futuretask實作了runnable,所有可通過executor(線程池)來執行,也可轉遞給thread對象來執行。如果在主線程中需要執行比較耗時的操作時,但又不想阻塞主線程時,可以把這些作業交給future對象在背景完成,當主線程将來需要時,就可以通過future對象獲得背景作業的計算結果或者執行狀态。

executor架構利用futuretask來完成異步任務,并可以用來進行任何潛在的耗時的計算。一般futuretask多用于耗時的計算,主線程可以在完成自己的任務後,再去擷取結果。

jdk提供了對future的基本實作,僅在計算完成後才能檢索結果,如果未完成,則阻塞get()方法,一旦計算完成,就不能重新開始或者取消。

可使用futtretask

包裝callable或者runnable對象。因為futuretask實作runnble,是以可将futuretask送出給executor執行。

構造方法摘要  

futuretask(callable<v> callable)   

          建立一個 futuretask,一旦運作就執行給定的 callable。  

futuretask(runnable runnable, v result)   

          建立一個 futuretask,一旦運作就執行給定的 runnable,并安排成功完成時 get 傳回給定的結果 。  

參數:  

runnable - 可運作的任務。  

result - 成功完成時要傳回的結果。  

如果不需要特定的結果,則考慮使用下列形式的構造:future<?> f = new futuretask<object>(runnable, null)

下面的例子模拟一個會計算賬的過程,主線程已經獲得其他帳戶的總額了,為了不讓主線程等待 privateaccount類的計算結果的傳回而啟用新的線程去處理, 并使用 futuretask對象來監控,這樣,主線程還可以繼續做其他事情, 最後需要計算總額的時候再嘗試去獲得privateaccount 的資訊。 

java FutureTask

package test;  

import java.util.random;  

import java.util.concurrent.callable;  

import java.util.concurrent.executionexception;  

import java.util.concurrent.futuretask;  

/** 

 * 

 * @author administrator 

 */  

@suppresswarnings("all")  

public class futuretaskdemo {  

    public static void main(string[] args) {  

        // 初始化一個callable對象和futuretask對象  

        callable paccount = new privateaccount();  

        futuretask futuretask = new futuretask(paccount);  

        // 使用futuretask建立一個線程  

        thread paccountthread = new thread(futuretask);  

        system.out.println("futuretask線程現在開始啟動,啟動時間為:" + system.nanotime());  

        paccountthread.start();  

        system.out.println("主線程開始執行其他任務");  

        // 從其他賬戶擷取總金額  

        int totalmoney = new random().nextint(100000);  

        system.out.println("現在你在其他賬戶中的總金額為" + totalmoney);  

        system.out.println("等待私有賬戶總金額統計完畢...");  

        // 測試背景的計算線程是否完成,如果未完成則等待  

        while (!futuretask.isdone()) {  

            try {  

                thread.sleep(500);  

                system.out.println("私有賬戶計算未完成繼續等待...");  

            } catch (interruptedexception e) {  

                e.printstacktrace();  

            }  

        }  

        system.out.println("futuretask線程計算完畢,此時時間為" + system.nanotime());  

        integer privateaccountmoney = null;  

        try {  

            privateaccountmoney = (integer) futuretask.get();  

        } catch (interruptedexception e) {  

            e.printstacktrace();  

        } catch (executionexception e) {  

        system.out.println("您現在的總金額為:" + totalmoney + privateaccountmoney.intvalue());  

    }  

}  

class privateaccount implements callable {  

    integer totalmoney;  

    @override  

    public object call() throws exception {  

        thread.sleep(5000);  

        totalmoney = new integer(new random().nextint(10000));  

        system.out.println("您目前有" + totalmoney + "在您的私有賬戶中");  

        return totalmoney;  

 運作結果 

futuretask線程現在開始啟動,啟動時間為:3098040622063 

主線程開始執行其他任務 

現在你在其他賬戶中的總金額為56983 

等待私有賬戶總金額統計完畢... 

私有賬戶計算未完成繼續等待... 

您目前有3345在您的私有賬戶中 

futuretask線程計算完畢,此時時間為3103072404138 

您現在的總金額為:569833345 

public class futuretasksample {  

    static futuretask<string> future = new futuretask(new callable<string>(){  

        public string call(){  

            return getpagecontent();  

    });  

    public static void main(string[] args) throws interruptedexception, executionexception{  

        //start a thread to let this thread to do the time exhausting thing  

        new thread(future).start();  

        //main thread can do own required thing first  

        doownthing();  

        //at the needed time, main thread can get the result  

        system.out.println(future.get());  

    public static string doownthing(){  

        return "do own thing";  

    public static string getpagecontent(){  

        return "testpagecontent and provide that the operation is a time exhausted thing...";  

}  

下面是callable 和 runnable的介紹:

編寫多線程程式是為了實作多任務的并發執行,進而能夠更好地與使用者互動。一般有三種方法,thread,runnable,callable.

runnable和callable的差別是,

(1)callable規定的方法是call(),runnable規定的方法是run().

(2)callable的任務執行後可傳回值,而runnable的任務是不能傳回值得

(3)call方法可以抛出異常,run方法不可以

(4)運作callable任務可以拿到一個future對象,表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,并檢索計算的結果。通過future對象可以了解任務執行情況,可取消任務的執行,還可擷取執行結果。

1、通過實作runnable接口來建立thread線程:

  步驟1:建立實作runnable接口的類:

class somerunnable implements runnable

{

    public void run()

    {

      //do something here

    }

}

通過線程池來建立線程:

步驟1:建立線程池:

      executorservice pool = executors.newcachedthreadpool();

步驟2:通過runnable對象或callable對象将任務送出給executorservice對象:

      future<integer> submit(callable<integer> task);

      注釋:future是一個接口,它的定義如下:

public interface future<t>

    v get() throws ...;

    v get(long timeout, timeunit unit) throws ...;

    void cancle(boolean mayinterrupt);

    boolean iscancelled();

    boolean isdone();

      至此,一個線程就建立完成了。

      注釋:線程池需調用shutdown();方法來關閉線程。