CompletableFuture的多线程和异步监听实现
生活随笔
收集整理的這篇文章主要介紹了
CompletableFuture的多线程和异步监听实现
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
大家好,我是烤鴨:
今天給大家說的是多線程并發(fā)的異步監(jiān)聽的情況。
這里不得不說一下CompletableFuture這個類,普通我們執(zhí)行多線程的時候只需要另外啟動一條線程。
說一下線程的3種方式:
如果他們有沒執(zhí)行完的,主線程就一直等。這樣就分工明確了,主線程的任務(wù)就是監(jiān)視其他是否完畢,
今天給大家說的是多線程并發(fā)的異步監(jiān)聽的情況。
這里不得不說一下CompletableFuture這個類,普通我們執(zhí)行多線程的時候只需要另外啟動一條線程。
說一下線程的3種方式:
extends Thread,implements Runnable,implements Callable。
? ? ? ? 同步的實現(xiàn)方式有很多。這里貼一下我的。
? ? ? ?這個handler是可以注入其他的比如service或者dao,完成業(yè)務(wù)邏輯,我這里是注入的redis。
package com.mys.my.wechat.handler;import com.mys.my.wechat.config.redis.RedisClient; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.Executor;@Service("musicHandler") public class MusicHandler {public static Log logger = LogFactory.getLog(MusicHandler.class);public String redisString;public String openId;@Autowiredprivate RedisClient redisClient;@Autowiredprivate Executor taskAsyncPool;public void doAllHandler() {try {taskAsyncPool.execute(new Runnable() {@Overridepublic void run() {logger.info("xiami 任務(wù)啟動");Date time = new Date(); // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // String re_StrTime = sdf.format(time);//過期時間1小時redisClient.set("xiamiMusic:"+openId,redisString,60*60);}});} catch (Exception e) {e.printStackTrace();}} }調(diào)用:
//存redismusicHandler.redisString = toJson;musicHandler.openId = openId;musicHandler.doAllMusicHandler();以上就是同步調(diào)用,但是這樣只是執(zhí)行,你無法監(jiān)聽結(jié)果。
我現(xiàn)在說一下場景:
燒水的同時,洗衣機(jī)洗衣服,電腦下載,手機(jī)充電,我們生活中也會有同時干幾件事的情況,而需求是這幾件事都干完了我才能出門,多線程確實能執(zhí)行,但是怎么監(jiān)聽結(jié)果呢。
以上也許可以說時間是可以預(yù)測的。
但是具體的業(yè)務(wù)場景,如果需要你去調(diào)用4個接口,而他們之間的沒有任何影響,但是又必須4個接口都執(zhí)行完才能返回數(shù)據(jù)。這樣如果實現(xiàn)多線程的異步監(jiān)聽呢?
最常用的就是爬蟲,我想同時抓取幾個網(wǎng)站或者幾個網(wǎng)頁的數(shù)據(jù),如果是單線程,效率很低。多線程又必須保證每條線程完成抓取并返回數(shù)據(jù)。以下是一個小例子。
用CompletableFuture,代碼如下:
package com.mys.my.wechat.service.impl;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.concurrent.CompletableFuture;final Integer res = 0;final ArrayList<Integer> integers = new ArrayList<>();CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {//模擬執(zhí)行耗時任務(wù)System.out.println("task 1 doing...");try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}//返回結(jié)果return 1;});//注冊完成事件completableFuture1.thenAccept(result -> {integers.add(1);});CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {//模擬執(zhí)行耗時任務(wù)System.out.println("task 2 doing...");try {Thread.sleep(2000);} catch (Exception e) {e.printStackTrace();}//返回結(jié)果return 1;});//注冊完成事件completableFuture2.thenAccept(result -> {integers.add(1);});CompletableFuture<Integer> completableFuture3 = CompletableFuture.supplyAsync(() -> {//模擬執(zhí)行耗時任務(wù)System.out.println("task 3 doing...");try {Thread.sleep(3000);} catch (Exception e) {e.printStackTrace();}//返回結(jié)果return 1;});//注冊完成事件completableFuture3.thenAccept(result -> {integers.add(1);});while(true){try {Thread.sleep(1000);if(integers.size()== 3){System.out.println("done");break;}System.out.println("s:"+integers.size());} catch (InterruptedException e) {e.printStackTrace();}}}這里我們可以看到,主線程一直在監(jiān)聽,其他新開啟的3個線程,如果他們執(zhí)行完畢,就可以返回數(shù)據(jù),如果他們有沒執(zhí)行完的,主線程就一直等。這樣就分工明確了,主線程的任務(wù)就是監(jiān)視其他是否完畢,
而同時開啟3條線程執(zhí)行速度也會很快。
這只是一個demo和想法實現(xiàn),歡迎交流。
總結(jié)
以上是生活随笔為你收集整理的CompletableFuture的多线程和异步监听实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从零开始攻略PHP(8)——面向对象(下
- 下一篇: centos7 时间设置