2010-10-29 50 views
1

我仍在學習如何在Java中使用Future和Callable。 跌入了這個問題:Java Future多線程如何返回結果?

說我有類:

TaskWorker implements Callable { 
    public String id; 
    public TaskWorker(String id) { 
    this.id = id; 
    } 

    public Documents call() trows Exception { 
     //Assume here, that Search and Doc are my own method to search and retrieve docs 
     Search search = new Search(); 
     Documents docResult = search.process(id); 

     //think about documents has getDocs 
     //docResult.getDocs() will return number of document found from search 

     return docResult; 
    } 
} 

這裏是主要的方法:

public static void main(String[] args) { 
    //assume here, that I build in request contains many Id 

    Request request = new Request(); 
    request.process; 

    ExecutorService service = Executors.newFixedThreadPool(3); 
    List<Future<Documents>> result = new ArrayList<Future<Documents>>(); 

    for (int i=0;i<request.length;i++) { 
     Callable<Documents> worker = new TaskWorker(request.getId[i]); 
     Future<Documents> submit = executor.submit(worker); 
     result.add(submit); 
    } 

    Response response = new Response(); 
    ArrayList<Documents> docList = new ArrayList<Documents>(); 

    for (Future<Documents> future:result) { 
    docList.add(future.get().getDocs()); 
    } 

    response.setDocuments(docList); 
} 

我所試圖做的是,打破了部分請求因爲每個請求ID都是獨立的搜索進程,所以在單獨的線程中運行。 所以我試圖通過將結果存儲在將來的對象中來利用Java池。

我很困惑的是,在這種情況下未來會如何工作? 對於每個線程完成,是否會保持結果?在所有的過程完成後,我可以循環未來的對象來獲得正確的結果?

此外,不保證進程將按順序(1,2,3,4等)運行,對不對? 如果是這種情況,那麼如果我想將每個原始請求與未來結果關聯起來,那麼最佳策略是什麼?

請指教。

感謝

回答

2

此外,也不能保證 進程將爲了 運行(1,2,3,4等),對不對?如果那 的情況下,那麼如果我想將每個原始的 請求與未來結果關聯起來,那麼最佳策略 是什麼?

你無法知道在後臺線程開始和結束的順序,但是當你遍歷你的結果,ArrayList中,你會得到的,當然,在訂單的結果,你提交信息。唯一可能發生的情況是.get()會阻塞,直到這個未來對象的特定結果可用(如果尚未可用)。

+0

哦,我明白了。是否有理由擔心在這裏使用Arraylist而不是Vector來解決線程安全問題? – javaWorker 2010-10-29 15:41:05

+0

另外,當然我忘了關閉ExecutorService。假設,我需要把它們放在未來循環之後,對吧? – javaWorker 2010-10-29 15:41:31

+1

您不必擔心結果ArrayList的線程安全性,因爲它只能從一個線程(主線程)訪問,而不能從任何後臺線程訪問。您應該在future-loop之後關閉ExecutorService。否則你的程序將不會退出,直到執行程序終止所有緩存的後臺線程。 – 2010-10-29 15:59:23

0

您應該創建SynchronizedMap,並在構造一個請求一起傳遞給TaskWorker。 TaskWorker應在完成作業時向地圖添加「請求」和「結果」。

您不必循環期貨以獲得結果,只需確保所有工作都已完成。