使用CompletionService非阻塞獲取多線程返回值

在Java編程中揍瑟,Java利用future及時(shí)獲取線程運(yùn)行結(jié)果的方法有兩種,第一種利用Future的isdone()和get()結(jié)合獲取乍炉,第二種利用java的concurrent包中的CompletionService提供的方法非阻塞獲取月培。

Future接口是Java標(biāo)準(zhǔn)API的一部分嘁字,在java.util.concurrent包中。Future接口是Java線程Future模式的實(shí)現(xiàn)杉畜,可以來(lái)進(jìn)行異步計(jì)算。
有了Future就可以進(jìn)行三段式的編程了衷恭,1.啟動(dòng)多線程任務(wù)2.處理其他事3.收集多線程任務(wù)結(jié)果此叠。從而實(shí)現(xiàn)了非阻塞的任務(wù)調(diào)用。在途中遇到一個(gè)問(wèn)題随珠,那就是雖然能異步獲取結(jié)果灭袁,但是Future的結(jié)果需要通過(guò)isdone來(lái)判斷是否有結(jié)果,或者使用get()函數(shù)來(lái)阻塞式獲取執(zhí)行結(jié)果窗看。這樣就不能實(shí)時(shí)跟蹤其他線程的結(jié)果狀態(tài)了茸歧,所以直接使用get還是要慎用,最好配合isdone來(lái)使用显沈。
有一種更好的方式來(lái)實(shí)現(xiàn)對(duì)任意一個(gè)線程運(yùn)行完成后的結(jié)果都能及時(shí)獲取的辦法:使用CompletionService软瞎,它內(nèi)部添加了阻塞隊(duì)列,從而獲取future中的值拉讯,然后根據(jù)返回值做對(duì)應(yīng)的處理涤浇。

利用Future的get()方法阻塞式獲取

/**
 * 多線程執(zhí)行,異步獲取結(jié)果
 */
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);
    }

    /**
     *  * 生成指定數(shù)量的線程魔慷,都放入future數(shù)組
     */
    public void generate(int threadNum, List<Future<String>> fList) {
        ExecutorService service = Executors.newFixedThreadPool(threadNum);
        for (int i = 0; i < threadNum; i++) {
            //submit與execute的區(qū)別在于submit有返回值只锭,一般對(duì)應(yīng)于callable
            Future<String> f = service.submit(getJob(i));
            fList.add(f);
    }
        service.shutdown();
    }

    /**
     *  * other things
     *  
     */
    public void doOtherThings() {
        System.out.println("now is yes");
    }

    /**
     *  * 從future中獲取線程結(jié)果,打印結(jié)果
     *  
     */
    public void getResult(List<Future<String>> fList) {
        ExecutorService service = Executors.newSingleThreadExecutor();
        service.execute(getCollectJob(fList));
        service.shutdown();
    }

    /**
     *  * 生成指定序號(hào)的線程對(duì)象
     *  
     */
    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;
            }
        };
    }

    /**
     *  * 生成結(jié)果收集線程對(duì)象
     */
    public Runnable getCollectJob(final List<Future<String>> fList) {
        return new Runnable() {
            public void run() {
                for (Future<String> future : fList) {
                    try {
                        //如果不采用while(true)將會(huì)是阻塞式獲取結(jié)果
                        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();
                    }
                }
            }
        };
    }
}

使用CompletionService非阻塞獲取多線程返回值

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

    /**
     *  * 使用completionService收集callable結(jié)果
     *  * @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;
    }

可以看出院尔,CompletionService編程更友好蜻展,簡(jiǎn)潔易懂。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末邀摆,一起剝皮案震驚了整個(gè)濱河市纵顾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌隧熙,老刑警劉巖片挂,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異贞盯,居然都是意外死亡音念,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門躏敢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)闷愤,“玉大人,你說(shuō)我怎么就攤上這事件余〖テ辏” “怎么了遭居?”我有些...
    開(kāi)封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)旬渠。 經(jīng)常有香客問(wèn)我俱萍,道長(zhǎng),這世上最難降的妖魔是什么告丢? 我笑而不...
    開(kāi)封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任枪蘑,我火速辦了婚禮,結(jié)果婚禮上岖免,老公的妹妹穿的比我還像新娘岳颇。我一直安慰自己,他們只是感情好颅湘,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布话侧。 她就那樣靜靜地躺著,像睡著了一般闯参。 火紅的嫁衣襯著肌膚如雪瞻鹏。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天赢赊,我揣著相機(jī)與錄音乙漓,去河邊找鬼。 笑死释移,一個(gè)胖子當(dāng)著我的面吹牛叭披,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播玩讳,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼涩蜘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了熏纯?” 一聲冷哼從身側(cè)響起同诫,我...
    開(kāi)封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎樟澜,沒(méi)想到半個(gè)月后误窖,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秩贰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年霹俺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毒费。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡丙唧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出觅玻,到底是詐尸還是另有隱情想际,我是刑警寧澤培漏,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站胡本,受9級(jí)特大地震影響牌柄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜侧甫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一友鼻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闺骚,春花似錦、人聲如沸妆档。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贾惦。三九已至胸梆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間须板,已是汗流浹背碰镜。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留习瑰,地道東北人绪颖。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像甜奄,于是被迫代替她去往敵國(guó)和親柠横。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容