Java多線程之批量發(fā)起請求

日常開發(fā)中可能會遇到批量發(fā)起請求的場景怠褐,如:從某個服務(wù)器拉取大批量數(shù)據(jù),如果一次拉取您宪,數(shù)據(jù)量太大奈懒。采用分頁拉取方式,一頁一頁拉取宪巨,比較耗時磷杏,此時我們可以批量的同時去拉數(shù)據(jù)。

如何發(fā)起批量請求呢捏卓?可以使用Java多線程去實(shí)現(xiàn)极祸。每個線程拉取數(shù)據(jù)的執(zhí)行時間可能不一致,我們希望先執(zhí)行完任務(wù)的線程可以優(yōu)先返回?cái)?shù)據(jù)怠晴,不是等待所有線程都執(zhí)行完遥金,才返回?cái)?shù)據(jù)。

Future方式

public static void sleep(long time) {
    try {
        TimeUnit.SECONDS.sleep(time);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
public static void test() {
    long start = System.currentTimeMillis();

    //定義ExecutorService
    ExecutorService executor = Executors.newFixedThreadPool(3);

    //定義批量任務(wù)蒜田,每個任務(wù)的耗時不等
    final List<Callable<Integer>> tasks = Arrays.asList(
            () -> {
                sleep(30L);
                System.out.println("Task 30 completed done.");
                return 30;
            },
            () -> {
                sleep(10L);
                System.out.println("Task 10 completed done.");
                return 10;
            },
            () -> {
                sleep(20L);
                System.out.println("Task 20 completed done.");
                return 20;
            }
    );

    //批量提交執(zhí)行異步任務(wù)稿械,
    try {
        List<Future<Integer>> futures = executor.invokeAll(tasks);
        futures.forEach(future -> {
            try {
                System.out.println("返回結(jié)果: " + future.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });
        executor.shutdown();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    long end = System.currentTimeMillis();
    long seed = end - start;
    System.out.format("seed=%s", seed);
}

執(zhí)行結(jié)果:

Task 30 completed done.
Task 10 completed done.
Task 20 completed done.
返回結(jié)果: 30
返回結(jié)果: 10
返回結(jié)果: 20
seed=30068

我們無法優(yōu)先獲取最先執(zhí)行完任務(wù)線程的結(jié)果,而是等到耗時(30s)最長的任務(wù)執(zhí)行完畢后才可以拿到結(jié)果物邑。

CompletableFuture方式

public static void test2() {
    long start = System.currentTimeMillis();

    List<String> list = Arrays.asList("1", "2", "3");
    List<CompletableFuture<String>> futures = list.stream()
            .map(item ->
                    CompletableFuture.supplyAsync(() -> {
                                if ("1".equals(item)) {
                                    sleep(10L);
                                } else if ("2".equals(item)) {
                                    sleep(30L);
                                } else {
                                    sleep(20L);
                                }

                                System.out.println("thread name: " + Thread.currentThread().getName() + " task: " + item);
                                return "任務(wù)" + item;
                            }
                    )).collect(Collectors.toList());

    futures.forEach(future -> {
        future.thenAccept(result -> {
            System.out.println("返回結(jié)果: " + result);
        });
    });

    futures.forEach(future -> {
        future.join();
    });

    long end = System.currentTimeMillis();
    long seed = end - start;
    System.out.format("seed=%s", seed);
}

執(zhí)行結(jié)果:

thread name: ForkJoinPool.commonPool-worker-9 task: 1
返回結(jié)果: 任務(wù)1
thread name: ForkJoinPool.commonPool-worker-11 task: 3
返回結(jié)果: 任務(wù)3
thread name: ForkJoinPool.commonPool-worker-2 task: 2
返回結(jié)果: 任務(wù)2
seed=30079

可以優(yōu)先拿到最先執(zhí)行完任務(wù)線程的執(zhí)行結(jié)果溜哮。

CompletionService方式

public static void test3() {
    long start = System.currentTimeMillis();
    //定義ExecutorService
    ExecutorService executor = Executors.newFixedThreadPool(3);

    //定義批量任務(wù),每個任務(wù)的耗時不等
    final List<Callable<Integer>> tasks = Arrays.asList(
            () -> {
                sleep(30L);
                System.out.println("Task 30 completed done.");
                return 30;
            },
            () -> {
                sleep(10L);
                System.out.println("Task 10 completed done.");
                return 10;
            },
            () -> {
                sleep(20L);
                System.out.println("Task 20 completed done.");
                return 20;
            }
    );

    //批量提交執(zhí)行異步任務(wù)色解,
    try {
        CompletionService<Integer> completionService = new ExecutorCompletionService<>(executor);
        tasks.forEach(completionService::submit);

        for (int i = 0; i < tasks.size(); i++) {
            try {
                System.out.println("返回結(jié)果: " + completionService.take().get());

            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        executor.shutdown();
    } catch (Exception e) {
        e.printStackTrace();
    }

    long end = System.currentTimeMillis();
    long seed = end - start;
    System.out.format("seed=%s", seed);
}

執(zhí)行結(jié)果:

Task 10 completed done.
返回結(jié)果: 10
Task 20 completed done.
Task 30 completed done.
返回結(jié)果: 20
返回結(jié)果: 30
seed=30064

可以優(yōu)先拿到最先執(zhí)行完任務(wù)線程的執(zhí)行結(jié)果茂嗓。

推薦

https://juejin.cn/post/6844904195162636295
http://www.reibang.com/p/2528550e94a9

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市科阎,隨后出現(xiàn)的幾起案子述吸,更是在濱河造成了極大的恐慌,老刑警劉巖锣笨,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝌矛,死亡現(xiàn)場離奇詭異,居然都是意外死亡错英,警方通過查閱死者的電腦和手機(jī)入撒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來椭岩,“玉大人茅逮,你說我怎么就攤上這事∨懈纾” “怎么了献雅?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長塌计。 經(jīng)常有香客問我挺身,道長,這世上最難降的妖魔是什么锌仅? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任章钾,我火速辦了婚禮,結(jié)果婚禮上热芹,老公的妹妹穿的比我還像新娘伍玖。我一直安慰自己,他們只是感情好剿吻,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布窍箍。 她就那樣靜靜地躺著,像睡著了一般丽旅。 火紅的嫁衣襯著肌膚如雪椰棘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天榄笙,我揣著相機(jī)與錄音邪狞,去河邊找鬼。 笑死茅撞,一個胖子當(dāng)著我的面吹牛帆卓,可吹牛的內(nèi)容都是我干的巨朦。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼剑令,長吁一口氣:“原來是場噩夢啊……” “哼糊啡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吁津,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤棚蓄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后碍脏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體梭依,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年典尾,在試婚紗的時候發(fā)現(xiàn)自己被綠了役拴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡钾埂,死狀恐怖扎狱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情勃教,我是刑警寧澤淤击,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站故源,受9級特大地震影響污抬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绳军,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一印机、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧门驾,春花似錦射赛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至聂沙,卻和暖如春秆麸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背及汉。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工沮趣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人坷随。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓房铭,卻偏偏與公主長得像驻龟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子缸匪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

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