成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

SpringBoot項目中異步調(diào)用接口方式知多少?

開發(fā) 項目管理
經(jīng)常會遇到在項目中調(diào)用第三方接口的情景,你是如何調(diào)用的呢?同步?異步?

[[388631]]

 環(huán)境:springboot2.3.9.RELEASE

經(jīng)常會遇到在項目中調(diào)用第三方接口的情景,你是如何調(diào)用的呢?同步?異步?

場景:

假設(shè)下單業(yè)務(wù)流程如下步驟:

1、查詢用戶信息。

2、查詢庫存信息。

3、查詢活動信息(折扣)。

1.同步順序調(diào)用

  1. public boolean createOrder() { 
  2.         long start = System.currentTimeMillis() ; 
  3.         String userResult = restTemplate.getForObject("http://localhost:8080/users/{1}", String.class, new Object[] {1}) ; 
  4.         String storageResult = restTemplate.getForObject("http://localhost:8080/storage/{1}", String.class, new Object[] {1}) ; 
  5.         String discountResult = restTemplate.getForObject("http://localhost:8080/discount/{1}", String.class, new Object[] {1}) ; 
  6.         // 這里合并請求結(jié)果處理 
  7.         System.out.println(Arrays.toString(new String[] {userResult, storageResult, discountResult})) ; 
  8.         System.out.println("傳統(tǒng)方式耗時:" + (System.currentTimeMillis() - start) + "毫秒") ; 
  9.         return true ; 
  10.     } 
  11.   @GetMapping("/create"
  12.     public Object create() { 
  13.         return os.createOrder() ; 
  14.     } 

 調(diào)用結(jié)果:


接口一個一個調(diào)用,非常耗時。

2.多線程(Callable+Future)

  1. public boolean createOrder2() { 
  2.         long start = System.currentTimeMillis() ; 
  3.         Callable<String> userCallable = () -> { 
  4.             return restTemplate.getForObject("http://localhost:8080/users/{1}", String.class, new Object[] {1}) ; 
  5.         } ; 
  6.         Callable<String> storageCallable = () -> { 
  7.             return restTemplate.getForObject("http://localhost:8080/storage/{1}", String.class, new Object[] {1}) ; 
  8.         } ; 
  9.         Callable<String> discountCallable = () -> { 
  10.             return restTemplate.getForObject("http://localhost:8080/discount/{1}", String.class, new Object[] {1}) ; 
  11.         } ; 
  12.         FutureTask<String> userTask = new FutureTask<>(userCallable) ; 
  13.         FutureTask<String> storageTask = new FutureTask<>(storageCallable) ; 
  14.         FutureTask<String> discountTask = new FutureTask<>(discountCallable) ; 
  15.         new Thread(userTask).start() ; 
  16.         new Thread(storageTask).start() ; 
  17.         new Thread(discountTask).start() ; 
  18.         try { 
  19.             String userResult = userTask.get() ; 
  20.             String storageResult = storageTask.get() ; 
  21.             String discountResult = discountTask.get() ; 
  22.             // 這里合并請求結(jié)果處理 
  23.             System.out.println(Arrays.toString(new String[] {userResult, storageResult, discountResult})) ; 
  24.         } catch (InterruptedException | ExecutionException e) { 
  25.             e.printStackTrace(); 
  26.         } 
  27.         System.out.println("多線程方式耗時:" + (System.currentTimeMillis() - start) + "毫秒") ; 
  28.         return true ; 
  29.     } 

 調(diào)用結(jié)果:


這次耗時少了,性能明顯提升了。但在項目中我們一般是禁止直接創(chuàng)建線程的,如果這是個高并發(fā)的接口,那么我們的程序很可能出現(xiàn)OOM的錯誤。

3.線程池(Callable+Future)防止內(nèi)存溢出風險

  1. ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000)) ; 
  2.     public boolean createOrder3() { 
  3.         long start = System.currentTimeMillis() ; 
  4.         List<Future<String>> results = new ArrayList<>(3) ; 
  5.         results.add(pool.submit(() -> { 
  6.             return restTemplate.getForObject("http://localhost:8080/users/{1}", String.class, new Object[] {1}) ; 
  7.         })) ; 
  8.         results.add(pool.submit(() -> { 
  9.             return restTemplate.getForObject("http://localhost:8080/storage/{1}", String.class, new Object[] {1}) ; 
  10.         })) ; 
  11.         results.add(pool.submit(() -> { 
  12.             return restTemplate.getForObject("http://localhost:8080/discount/{1}", String.class, new Object[] {1}) ; 
  13.         })) ; 
  14.         for (int i = 0, size = results.size(); i < size; i++) { 
  15.             try { 
  16.                 System.out.println(results.get(i).get()) ; 
  17.             } catch (InterruptedException | ExecutionException e) { 
  18.                 e.printStackTrace(); 
  19.             } 
  20.         } 
  21.         System.out.println("線程池方式耗時:" + (System.currentTimeMillis() - start) + "毫秒") ; 
  22.         return true ; 
  23.     } 

 調(diào)用結(jié)果:


耗時和上一個基本一致,通過Future的方式有一個問題就是只能一個一個的取值,只有當前的返回數(shù)據(jù)了后才會繼續(xù)往下執(zhí)行。如果有其它的任務(wù)執(zhí)行完,那沒有輪到它也必須等待。

4.CompletionService(異步任務(wù)與使用已完成任務(wù)的結(jié)果分離),submit提交任務(wù),take獲取已經(jīng)完成的任務(wù),不用按照submit的順序獲取結(jié)果。

  1. public boolean createOrder4() { 
  2.         long start = System.currentTimeMillis() ; 
  3.         CompletionService<String> cs = new ExecutorCompletionService<>(pool) ; 
  4.         cs.submit(() -> { 
  5.             return restTemplate.getForObject("http://localhost:8080/users/{1}", String.class, new Object[] {1}) ; 
  6.         }) ; 
  7.         cs.submit(() -> { 
  8.             return restTemplate.getForObject("http://localhost:8080/storage/{1}", String.class, new Object[] {1}) ; 
  9.         }) ; 
  10.         cs.submit(() -> { 
  11.             return restTemplate.getForObject("http://localhost:8080/discount/{1}", String.class, new Object[] {1}) ; 
  12.         }) ; 
  13.         for (int i = 2 ; i >=0; i--) { 
  14.             try { 
  15.                 System.out.println(cs.take().get()) ; 
  16.             } catch (InterruptedException | ExecutionException e) { 
  17.                 e.printStackTrace(); 
  18.             } 
  19.         } 
  20.         System.out.println("CompletionService方式耗時:" + (System.currentTimeMillis() - start) + "毫秒") ; 
  21.         return true ; 
  22.     } 

 調(diào)用結(jié)果:


通過CompletionService方式不管任務(wù)添加的順序是什么,只要通過take方法就能獲取執(zhí)行完的結(jié)果,如果沒有任務(wù)執(zhí)行完,take方法會阻塞。

5.CompletableFuture(異步任務(wù)編排),JDK1.8

  1. public boolean createOrder5() { 
  2.         long start = System.currentTimeMillis() ; 
  3.         CompletableFuture<String> userFuture = CompletableFuture.supplyAsync(() -> { 
  4.             return restTemplate.getForObject("http://localhost:8080/users/{1}", String.class, new Object[] {1}) ; 
  5.         }) ; 
  6.          
  7.         CompletableFuture<String> storageFuture = CompletableFuture.supplyAsync(() -> { 
  8.             return restTemplate.getForObject("http://localhost:8080/storage/{1}", String.class, new Object[] {1}) ; 
  9.         }) ; 
  10.          
  11.         CompletableFuture<String> discountFuture = CompletableFuture.supplyAsync(() -> { 
  12.             return restTemplate.getForObject("http://localhost:8080/discount/{1}", String.class, new Object[] {1}); 
  13.         }) ; 
  14.         CompletableFuture<List<String>> result = CompletableFuture 
  15.                 .allOf(userFuture, storageFuture, discountFuture) 
  16.                 .thenApply((Void) -> { 
  17.                     List<String> datas = new ArrayList<>() ; 
  18.                     try { 
  19.                         datas.add(userFuture.get()) ; 
  20.                         datas.add(storageFuture.get()) ; 
  21.                         datas.add(discountFuture.get()) ; 
  22.                     } catch (InterruptedException | ExecutionException e) { 
  23.                         e.printStackTrace(); 
  24.                     } 
  25.                     return datas ; 
  26.                 }).exceptionally(e -> { 
  27.                     e.printStackTrace() ; 
  28.                     return null ; 
  29.                 }) ; 
  30.         try { 
  31.             System.out.println(result.get()) ; 
  32.         } catch (InterruptedException | ExecutionException e1) { 
  33.             e1.printStackTrace(); 
  34.         } 
  35.         System.out.println("CompletableFuture方式耗時:" + (System.currentTimeMillis() - start) + "毫秒") ; 
  36.         return true ; 
  37.     } 

 調(diào)用結(jié)果:


CompletableFuture提供了非常強大的異步編程方法,可同步,可異步,可編排任務(wù)執(zhí)行,異步通過回調(diào)的方式執(zhí)行。該對象很多的一些方法與前端JavaScript中的Promise對象有點相像。

 

責任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2023-08-23 13:24:00

異步編程方法

2021-03-29 09:26:44

SpringBoot異步調(diào)用@Async

2021-12-10 07:47:30

Javascript異步編程

2022-09-27 12:01:56

Spring異步調(diào)用方式

2010-03-01 14:01:50

WCF服務(wù)異步調(diào)用

2009-10-20 16:48:30

C#委托

2024-10-15 10:28:43

2018-12-12 15:01:22

開源存儲 軟件

2009-11-09 10:50:30

WCF異步調(diào)用

2009-12-21 14:10:26

WCF異步調(diào)用

2021-03-30 10:46:42

SpringBoot計數(shù)器漏桶算法

2022-09-28 14:54:07

Spring注解方式線程池

2009-11-06 15:54:15

WCF異步調(diào)用

2009-07-01 13:58:00

JavaScript異

2010-02-22 13:28:05

WCF異步調(diào)用

2009-08-21 11:24:16

C#異步調(diào)用

2009-07-01 14:05:23

JavaScript異

2009-07-01 14:37:14

JavaScript異

2009-07-01 14:23:46

JavaScript異

2009-12-07 14:35:42

WCF異步調(diào)用
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 久久久久久一区 | 欧美日韩高清 | 亚洲福利电影网 | 国产激情一区二区三区 | 久综合| 国产视频久久久 | 亚洲天堂av一区 | 992人人草| 99精品欧美一区二区蜜桃免费 | 亚洲成人av | 国产目拍亚洲精品99久久精品 | 一级毛片免费 | 欧美日韩亚洲在线 | 久久天天躁狠狠躁夜夜躁2014 | 日韩在线中文字幕 | 一区二区不卡 | 中文字幕视频一区 | 一区二区三区免费网站 | 欧美黄色片 | 久久首页 | 亚洲视频一区在线观看 | 中文字幕在线二区 | 成人精品在线观看 | 国产三级 | 色综合久 | 欧美一级片在线播放 | 91精品久久久久久久久 | 久久久精品天堂 | 新av在线| 午夜免费福利影院 | 成人免费av| 久久国产精品网站 | 日韩欧美一级 | 91精品国产一区二区 | 亚洲精品v | 91精品久久久久久久久久小网站 | 欧美日韩在线免费观看 | 亚洲视频在线观看 | 精品国产一二三区 | 午夜性色a√在线视频观看9 | 99精品网 |