日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747


環(huán)境:springboot2.5.12

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

場景:

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

1、查詢用戶信息。

2、查詢庫存信息。

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

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

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

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

圖片圖片

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

2、多線程(Callable+Future)

public boolean createOrder2() {
  long start = System.currentTimeMillis() ;
  Callable<String> userCallable = () -> {
    return restTemplate.getForObject("http://localhost:8080/users/{1}", String.class, new Object[] {1}) ;
  } ;
  Callable<String> storageCallable = () -> {
    return restTemplate.getForObject("http://localhost:8080/storage/{1}", String.class, new Object[] {1}) ;
  } ;
  Callable<String> discountCallable = () -> {
    return restTemplate.getForObject("http://localhost:8080/discount/{1}", String.class, new Object[] {1}) ;
  } ;
  FutureTask<String> userTask = new FutureTask<>(userCallable) ;
  FutureTask<String> storageTask = new FutureTask<>(storageCallable) ;
  FutureTask<String> discountTask = new FutureTask<>(discountCallable) ;
  new Thread(userTask).start() ;
  new Thread(storageTask).start() ;
  new Thread(discountTask).start() ;
  try {
    String userResult = userTask.get() ;
    String storageResult = storageTask.get() ;
    String discountResult = discountTask.get() ;
    // 這里合并請求結(jié)果處理
    System.out.println(Arrays.toString(new String[] {userResult, storageResult, discountResult})) ;
  } catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
  }
  System.out.println("多線程方式耗時:" + (System.currentTimeMillis() - start) + "毫秒") ;
  return true ;
}

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

圖片圖片

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

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

ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000)) ;
  public boolean createOrder3() {
  long start = System.currentTimeMillis() ;
  List<Future<String>> results = new ArrayList<>(3) ;
  results.add(pool.submit(() -> {
      return restTemplate.getForObject("http://localhost:8080/users/{1}", String.class, new Object[] {1}) ;
  })) ;
  results.add(pool.submit(() -> {
      return restTemplate.getForObject("http://localhost:8080/storage/{1}", String.class, new Object[] {1}) ;
  })) ;
  results.add(pool.submit(() -> {
    return restTemplate.getForObject("http://localhost:8080/discount/{1}", String.class, new Object[] {1}) ;
  })) ;
  for (int i = 0, size = results.size(); i < size; i++) {
    try {
      System.out.println(results.get(i).get()) ;
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
  }
  System.out.println("線程池方式耗時:" + (System.currentTimeMillis() - start) + "毫秒") ;
  return true ;
}

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

圖片圖片

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

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

public boolean createOrder4() {
  long start = System.currentTimeMillis() ;
  CompletionService<String> cs = new ExecutorCompletionService<>(pool) ;
  cs.submit(() -> {
    return restTemplate.getForObject("http://localhost:8080/users/{1}", String.class, new Object[] {1}) ;
  }) ;
  cs.submit(() -> {
    return restTemplate.getForObject("http://localhost:8080/storage/{1}", String.class, new Object[] {1}) ;
  }) ;
  cs.submit(() -> {
    return restTemplate.getForObject("http://localhost:8080/discount/{1}", String.class, new Object[] {1}) ;
  }) ;
  for (int i = 2 ; i >=0; i--) {
    try {
      System.out.println(cs.take().get()) ;
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
  }
  System.out.println("CompletionService方式耗時:" + (System.currentTimeMillis() - start) + "毫秒") ;
  return true ;
}

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

圖片圖片

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

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

public boolean createOrder5() {
  long start = System.currentTimeMillis() ;
  CompletableFuture<String> userFuture = CompletableFuture.supplyAsync(() -> {
    return restTemplate.getForObject("http://localhost:8080/users/{1}", String.class, new Object[] {1}) ;
  }) ;
    
  CompletableFuture<String> storageFuture = CompletableFuture.supplyAsync(() -> {
    return restTemplate.getForObject("http://localhost:8080/storage/{1}", String.class, new Object[] {1}) ;
  }) ;
    
  CompletableFuture<String> discountFuture = CompletableFuture.supplyAsync(() -> {
    return restTemplate.getForObject("http://localhost:8080/discount/{1}", String.class, new Object[] {1});
  }) ;
  CompletableFuture<List<String>> result = CompletableFuture
      .allOf(userFuture, storageFuture, discountFuture)
      .thenApply((Void) -> {
        List<String> datas = new ArrayList<>() ;
        try {
          datas.add(userFuture.get()) ;
          datas.add(storageFuture.get()) ;
          datas.add(discountFuture.get()) ;
        } catch (InterruptedException | ExecutionException e) {
          e.printStackTrace();
        }
        return datas ;
      }).exceptionally(e -> {
        e.printStackTrace() ;
        return null ;
      }) ;
  try {
    System.out.println(result.get()) ;
  } catch (InterruptedException | ExecutionException e1) {
    e1.printStackTrace();
  }
  System.out.println("CompletableFuture方式耗時:" + (System.currentTimeMillis() - start) + "毫秒") ;
  return true ;
}

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

圖片圖片

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

完畢!!!

分享到:
標(biāo)簽:SpringBoot
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定