1. 程式人生 > >利用Future非同步獲取多執行緒的返回結果

利用Future非同步獲取多執行緒的返回結果

Future介面是Java標準API的一部分,在java.util.concurrent包中。Future介面是Java執行緒Future模式的實現,可以來進行非同步計算。

有了Future就可以進行三段式的程式設計了,1.啟動多執行緒任務2.處理其他事3.收集多執行緒任務結果。從而實現了非阻塞的任務呼叫。在途中遇到一個問題,那就是雖然能非同步獲取結果,但是Future的結果需要通過isdone來判斷是否有結果,或者使用get()函式來阻塞式獲取執行結果。這樣就不能實時跟蹤其他執行緒的結果狀態了,所以直接使用get還是要慎用,最好配合isdone來使用。

這裡有一種更好的方式來實現對任意一個執行緒執行完成後的結果都能及時獲取的辦法:使用CompletionService,它內部添加了阻塞佇列,從而獲取future中的值,然後根據返回值做對應的處理。一般future使用和CompletionService使用的兩個測試案例如下:

1. 獲取到的結果的順序和Future放入列表的順序一致

複製程式碼
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 多執行緒執行,非同步獲取結果
 * 
 * @author
i-clarechen * */ public class AsyncThread { public static void main(String[] args) { AsyncThread t = new AsyncThread(); List<Future<String>> futureList = new ArrayList<Future<String>>(); t.generate(3, futureList); t.doOtherThings(); t.getResult(futureList); }
/** * 生成指定數量的執行緒,都放入future陣列 * * @param threadNum * @param fList */ public void generate(int threadNum, List<Future<String>> fList) { ExecutorService service = Executors.newFixedThreadPool(threadNum); for (int i = 0; i < threadNum; i++) { Future<String> f = service.submit(getJob(i)); fList.add(f); } service.shutdown(); } /** * other things */ public void doOtherThings() { try { for (int i = 0; i < 3; i++) { System.out.println("do thing no:" + i); Thread.sleep(1000 * (new Random().nextInt(10))); } } catch (InterruptedException e) { e.printStackTrace(); } } /** * 從future中獲取執行緒結果,列印結果 * * @param fList */ public void getResult(List<Future<String>> fList) { ExecutorService service = Executors.newSingleThreadExecutor(); service.execute(getCollectJob(fList)); service.shutdown(); } /** * 生成指定序號的執行緒物件 * * @param i * @return */ public Callable<String> getJob(final int i) { final int time = new Random().nextInt(10); return new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(1000 * time); return "thread-" + i; } }; } /** * 生成結果收集執行緒物件 * * @param fList * @return */ public Runnable getCollectJob(final List<Future<String>> fList) { return new Runnable() { public void run() { for (Future<String> future : fList) { try { while (true) { if (future.isDone() && !future.isCancelled()) { System.out.println("Future:" + future + ",Result:" + future.get()); break; } else { Thread.sleep(1000); } } } catch (Exception e) { e.printStackTrace(); } } } }; } }
複製程式碼

執行結果列印和future放入列表時的順序一致,為0,1,2:

複製程式碼
do thing no:0
do thing no:1
do thing no:2
Future:[email protected],Result:thread-0
Future:[email protected],Result:thread-1
Future:[email protected],Result:thread-2
複製程式碼

2. 先獲取到最先結束的執行緒結果

複製程式碼
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;


public class testCallable {
    public static void main(String[] args) {
        try {
            completionServiceCount();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

  
    /**
     * 使用completionService收集callable結果
     * @throws ExecutionException 
     * @throws InterruptedException 
     */
    public static void completionServiceCount() throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(
                executorService);
        int threadNum = 5;
        for (int i = 0; i < threadNum; i++) {
            completionService.submit(getTask(i));
        }
        int sum = 0;
        int temp = 0;
        for(int i=0;i<threadNum;i++){
            temp = completionService.take().get();
            sum += temp;
            System.out.print(temp + "\t");
        }
        System.out.println("CompletionService all is : " + sum);
        executorService.shutdown();
    }

    public static Callable<Integer> getTask(final int no) {
        final Random rand = new Random();
        Callable<Integer> task = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int time = rand.nextInt(100)*100;
                System.out.println("thead:"+no+" time is:"+time);
                Thread.sleep(time);
                return no;
            }
        };
        return task;
    }
}
複製程式碼

執行結果為最先結束的執行緒結果先被處理:

複製程式碼
thead:0 time is:4200
thead:1 time is:6900
thead:2 time is:2900
thead:3 time is:9000
thead:4 time is:7100
2    0    1    4    3    CompletionService all is : 10

相關推薦

java 利用Future非同步獲取執行任務結果

Future介面是Java標準API的一部分,在java.util.concurrent包中。Future介面是Java執行緒Future模式的實現,可以來進行非同步計算。 有了Future就可以進行三段式的程式設計了,1.啟動多執行緒任務2.處理其他事3.收集多執行緒任務結果。從而實現了非阻塞

利用Future非同步獲取執行返回結果

Future介面是Java標準API的一部分,在java.util.concurrent包中。Future介面是Java執行緒Future模式的實現,可以來進行非同步計算。 有了Future就可以進行三段式的程式設計了,1.啟動多執行緒任務2.處理其他事3.收集多執行

Java執行池及Future、Callable獲得執行返回結果

Java執行緒池及Future、Callable獲得執行緒返回結果【Java執行緒池系列2】 Java多執行緒程式設計中,經常使用的Thread的Runnable()雖然被經常使用,但其有一個弊端,就是因為無法直接獲取該執行緒的返回值,因為Runnable內的run方法,

執行 : 使用 Future 獲取執行返回結果

import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.Execution

Python建立執行任務並獲取每個執行返回

轉自:https://www.cnblogs.com/bethansy/p/7965820.html 1.程序和執行緒     (1)程序是一個執行中的程式。每個程序都擁有自己的地址空間、記憶體、資料棧以及其他用於跟蹤執行的輔助資料。程序也可以派生新的程序來執行其他任務,

利用web work實現執行非同步機制,打造頁面單步除錯IDE

我們已經完成了整個編譯器的開發,現在我們做一個能夠單步除錯的頁面IDE,完成本章程式碼後,我們可以實現下面如圖所示功能: 頁面IDE可以顯示每行程式碼所在的行,單擊某一行,在改行前面會出現一個紅點表示斷點,點選Parsing按鈕後,進入單步除錯模式,然後每點一次step按鈕,頁

python 獲取 執行返回

import time import threading class MyThread(threading.Thread): def __init__(self, target=None, args=(), **kwargs): super(MyThread

深入Callable及Runnable兩個介面 獲取執行返回結果

-今天碰到一個需要獲取執行緒返回結果的業務場景,所以瞭解到了Callable介面。 先來看下下面這個例子: public class ThreadTest { public static void main(String[] args) throws Exception {

AsyncContext非同步執行區別

AsyncContext不是非同步輸出時使用的,而是同步輸出,但是解放伺服器端的執行緒使用,使用AsyncContext的時候,對於瀏覽器來說,他們是同步在等待輸出的,但是對於伺服器端來說,處理此請求的執行緒並沒有卡在那裡等待,則是把當前的處理轉為執行緒池處理了,關鍵就在於執行緒池,伺服器端會起一個執行緒

併發程式設計、並行、執行、鎖、同步、非同步執行、單執行、阻塞io、非阻塞io

一、 cpu的每一個核在同一時間下,只能執行一個執行緒,就是單核同一時間只能執行一個執行緒 而cpu可以不停的切換,這樣就導致使用者感覺可以執行多個執行緒,這是併發,而不是並行 併發和並行 你吃飯吃到一半,電話來了,你一直到吃完了以後才去接,這就說明你不支援併發也不支

同步、非同步執行、高併發不再混淆!

高併發:“短時間內遇到大量操作請求”的情況。 多執行緒:多執行緒就是指一個程序中同時有多個執行緒正在執行。其目的就是當某個執行緒很耗時的時候使用多執行緒,可以在將耗時任務放在後臺繼續執行的同時,同時執行其他操作,達到提升效率,優化使用者體驗的效果。 多執行緒是完成高併發任

android 利用java中的執行和io流,最快速度的下載伺服器檔案,android 實現apk下載展現通知欄

首先,我們得來說下多執行緒下載實現的大致思路,以及在使用多執行緒下載過程應該需要注意的問題。      多執行緒下載實現的大致思路:      大致思路是這樣的,也就是把整個一個檔案資源分為若干個部分,然後開啟若干個執行緒,並且使得每個執行緒負責下載每個子部分的檔案,由於

非同步執行有什麼區別

非同步呼叫並不是要減少執行緒的開銷, 它的主要目的是讓呼叫方法的主執行緒不需要同步等待在這個函式呼叫上, 從而可以讓主執行緒繼續執行它下面的程式碼.與此同時, 系統會通過從ThreadPool中取一個執行緒來執行,幫助我們將我們要寫/讀的資料傳送到網絡卡.由於不需要我們等待, 我們等於同時做了兩件事情. 這

C# 獲取執行ID

【文章標題】: 亂塗C#多執行緒02 【文章作者】: 有酒醉 【作者郵箱】: [email protected] 【下載地址】: 自己搜尋下載 【作者宣告】: 只是感興趣,沒有其他目的。失誤之處敬請諸位大俠賜教! 【詳細過程】 採用執行

利用程序ID獲取執行ID

(1)好像可以用StartTime最早的,不過通過執行緒執行時間不一定可靠,要是在最開始就CreateThread了,執行緒的執行時間會相同。可以通過回溯棧上的值來判斷哪個執行緒是主執行緒,主執行緒的棧多少有些不同。最明顯就是主執行緒棧上的PE入口點 資訊,沒有這個的就是子執行緒。 (2)CsrProcess

執行返回值的例子

當我們面臨大量資料查詢的時候,在我有限的技術生涯中,想到兩種解決方案。 1.建立專業的solr查詢引擎,實現全文檢索。 2.多執行緒加速查詢的過程。 後臺管理系統,資料量不算大,但是來源較多。較雜。 目前的處理方式是用多執行緒實現。 那麼,問題來了,多執行緒

spring執行返回值 並對返回值進行操作

最近遇到一個問題:有一大堆的債券,需要根據不同類別的標籤進行篩選出需要的債券,並且還要根據條件對這些標籤分別進行並和或操作。 最終決定使用callable+future來實現: 具體程式碼如下: @RequestMapping("/test") public Object

併發和並行,非同步執行區別

在單CPU系統中,系統排程在某一時刻只能讓一個執行緒執行,雖然這種除錯機制有多種形式(大多數是時間片輪巡為主),但無論如何,要通過不斷切換需要執行的執行緒讓其執行的方式就叫併發(concurrent)。而在多CPU系統中,可以讓兩個以上的執行緒同時執行,這種可以同時讓兩個以上執行緒同時執行的方式叫做並行(p

執行池(Java中有哪些方法獲取執行

# 執行緒池(Java中有哪些方法獲取多執行緒) ## 前言 獲取多執行緒的方法,我們都知道有三種,還有一種是實現Callable介面 - 實現Runnable介面 - 實現Callable介面 - 例項化Thread類 - 使用執行緒池獲取 ## Callable介面 Callable介面,是一種

C#中的非同步執行

許多開發人員對非同步程式碼和多執行緒以及它們的工作原理和使用方法都有錯誤的認識。在這裡,你將瞭解這兩個概念之間的區別,並使用c#實現它們。 我:“服務員,這是我第一次來這家餐廳。通常需要4個小時才能拿到食物嗎?” 服務員:“哦,是的,先生。這家餐廳的廚房裡只有一個廚師。” 我:“……只有一個廚師嗎?” 服務員