Java實(shí)現(xiàn)Promise.all()的示例代碼
JavaScript的Promise.all()
Promise是JavaScript異步編程的一種解決方案,在ES6中引入。
通過Promise.all()可以實(shí)現(xiàn)對一組異步請求的統(tǒng)一處理,等待所有異步執(zhí)行完成之后調(diào)用回調(diào)函數(shù)。
其實(shí),這種并發(fā)執(zhí)行同步等待的需求在Java并發(fā)編程中也很常見,那么,是否可以通過Java也來實(shí)現(xiàn)這樣一個Promise類呢?
使用Java實(shí)現(xiàn)Promise.all()
使用工具
CountDownLatch:Java并發(fā)工具包中有CountDownLatch類允許一個或多個線程等待其他線程的一系列操作完成。
ThreadPoolExecutor:通過線程池實(shí)現(xiàn)多線程的并發(fā)執(zhí)行
實(shí)現(xiàn)
public class Promise { private static ExecutorService executorService = Executors.newScheduledThreadPool(16); private Promise() { throw new AssertionError(); } /** * 實(shí)現(xiàn)并發(fā)同時地對某個action并發(fā)執(zhí)行并返回執(zhí)行結(jié)果 * 實(shí)現(xiàn)思路: * 并發(fā)創(chuàng)建所有執(zhí)行的線程,并通過鎖(start)阻塞等待著 * 在創(chuàng)建所有執(zhí)行的線程后(ready)開始計時,并解鎖然所有的線程啟動 * 通過另外一個鎖(done)記錄執(zhí)行完的線程 * 主線程只需關(guān)心3點(diǎn) * - 所有線程是否準(zhǔn)備好 * - 準(zhǔn)備好的話開始計時并解鎖開始執(zhí)行 * - 等待執(zhí)行完畢 * * @param callableList 要并發(fā)執(zhí)行的列表 * @return list 執(zhí)行結(jié)果,list.item為null的話表示執(zhí)行異常 * @throws InterruptedException 異常 */ public static <T> List<T> all(final List<Callable<T>> callableList) throws InterruptedException { final List<T> result = new ArrayList<>(); int length = callableList.size(); final CountDownLatch ready = new CountDownLatch(length); final CountDownLatch start = new CountDownLatch(1); final CountDownLatch done = new CountDownLatch(length); for (final Callable<T> callable : callableList) { executorService.execute(new Runnable() { @Override public void run() { ready.countDown(); try { start.await(); T t = callable.call(); result.add(t); } catch (Exception e) { // interrupt when exception Thread.currentThread().interrupt(); // set null mean exception result.add(null); e.printStackTrace(); } finally { done.countDown(); } } }); } ready.await(); long startnano = System.nanoTime(); start.countDown(); done.await(); long cause = System.nanoTime() - startnano; System.out.println(String.format("Promise all done,cause time millSecond: %s", cause / 1000000)); return result; } }
效果
測試
public void promiseAllTest() throws Exception{ List<Callable<String>> callables = new ArrayList<>(); for (int i = 0; i < 10; i++) { int finalI = i; callables.add(new Callable<String>() { @Override public String call() throws Exception { int millis = new Random().nextInt(10000); Thread.sleep(millis); System.out.println(String.format("thread%s sleep %s millis" ,finalI,millis)); return "Thread" + finalI; } }); } List<String> result = Promise.all(callables); System.out.println(result); System.out.println("done..."); }
測試結(jié)果
thread1 sleep 732 millis
thread2 sleep 758 millis
thread7 sleep 976 millis
thread8 sleep 1397 millis
thread5 sleep 1513 millis
thread0 sleep 2221 millis
thread3 sleep 4885 millis
thread6 sleep 5221 millis
thread4 sleep 7101 millis
thread9 sleep 7634 millis
Promise all done,cause time millSecond: 7638
[Thread1, Thread2, Thread7, Thread8, Thread5, Thread0, Thread3, Thread6, Thread4, Thread9]
done...
總結(jié)
本文只是通過原生Java實(shí)現(xiàn)簡單版本的Promise.all(),可用于簡單的并發(fā)編程,但是對于實(shí)際高并發(fā)應(yīng)用還需要優(yōu)化,如對線程池的優(yōu)化,還有中斷的處理等。
參考
《Effective Java》第二版第十章第69條:并發(fā)工具優(yōu)先于wait和notify
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JSP 獲取spring容器中bean的兩種方法總結(jié)
這篇文章主要介紹了JSP 獲取spring容器中bean的方法總結(jié)的相關(guān)資料,需要的朋友可以參考下2017-05-05SpringBoot+kaptcha實(shí)現(xiàn)圖片驗證碼功能詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何結(jié)合kaptcha實(shí)現(xiàn)圖片驗證碼功能,文中的示例代碼講解詳細(xì),有需要的小伙伴可以參考一下2024-01-01Springboot應(yīng)用中線程池配置詳細(xì)教程(最新2021版)
這篇文章主要介紹了Springboot應(yīng)用中線程池配置教程(2021版),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03IntelliJ IDEA 下載安裝超詳細(xì)教程(推薦)
這篇文章主要介紹了IntelliJ IDEA 下載安裝超詳細(xì)教程(推薦),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02詳解JAVA 線程-線程的狀態(tài)有哪些?它是如何工作的?
這篇文章主要介紹了詳解JAVA 線程的的相關(guān)資料,文中講解非常細(xì)致,源碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以參考下2020-06-06關(guān)于mybatis一對一查詢一對多查詢遇到的問題
這篇文章主要介紹了關(guān)于mybatis一對一查詢,一對多查詢遇到的錯誤,接下來是對文章進(jìn)行操作,要求查詢?nèi)课恼?,并關(guān)聯(lián)查詢作者,文章標(biāo)簽,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05