假如我有一個訂單相關的統計接口,須要返回3樣數據:今日訂單數、今日交易額、總交易額。java
通常的咱們的作法是串行調用3個函數,把調用返回的結果返回給調用者,這3次調用時串行執行的,若是每一個調用耗時1秒的話,3次調用總耗時就是3秒。web
這種作法效率很是低,由於3次調用之間無所謂前後順序,因此採用並行執行效率會更好。好比使用線程池ExecutorService實現異步調用。spring
其實Java8提供了一個很是牛逼的CompletableFuture類,也能夠實現異步化:json
1 import lombok.extern.slf4j.Slf4j; 2 import org.springframework.stereotype.Service; 3 4 import java.util.concurrent.CompletableFuture; 5 import java.util.concurrent.TimeUnit; 6 7 @Slf4j 8 @Service 9 public class OrderService { 10 11 /** 12 * 今日訂單數 13 * 14 * @return 15 */ 16 public CompletableFuture<String> todayOrderCount() { 17 return CompletableFuture.supplyAsync(() -> this.getTodayOrderCount()); 18 } 19 20 public CompletableFuture<String> todayTurnover() { 21 return CompletableFuture.supplyAsync(() -> this.getTodayTurnover()); 22 } 23 24 public CompletableFuture<String> totalTurnover() { 25 return CompletableFuture.supplyAsync(() -> this.getTotalTurnover()); 26 } 27 28 private String getTodayOrderCount() { 29 System.out.println(">>>>>>> 查詢今日訂單數:" + Thread.currentThread().getName()); 30 try { 31 TimeUnit.SECONDS.sleep(1); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 return "50"; 36 } 37 38 /** 39 * 今日交易額 40 * 41 * @return 42 */ 43 private String getTodayTurnover() { 44 System.out.println(">>>>>>> 查詢今日交易額:" + Thread.currentThread().getName()); 45 try { 46 TimeUnit.SECONDS.sleep(1); 47 } catch (InterruptedException e) { 48 e.printStackTrace(); 49 } 50 return "200"; 51 } 52 53 /** 54 * 總交易額 55 * 56 * @return 57 */ 58 private String getTotalTurnover() { 59 System.out.println(">>>>>>> 查詢總交易額:" + Thread.currentThread().getName()); 60 try { 61 TimeUnit.SECONDS.sleep(1); 62 } catch (InterruptedException e) { 63 e.printStackTrace(); 64 } 65 return "800"; 66 } 67 }
1 import com.alibaba.fastjson.JSONObject; 2 import com.example.sb.service.test.impl.OrderService; 3 import lombok.extern.slf4j.Slf4j; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.web.bind.annotation.GetMapping; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 import org.springframework.web.bind.annotation.RestController; 8 9 import java.util.concurrent.CompletableFuture; 10 11 @Slf4j 12 @RestController 13 @RequestMapping("/order") 14 public class OrderController { 15 16 @Autowired 17 private OrderService orderService; 18 19 @GetMapping("/report") 20 public JSONObject report() { 21 long start = System.currentTimeMillis(); 22 JSONObject json = orderReport(); 23 System.out.println("耗時:" + (System.currentTimeMillis() - start)); 24 return json; 25 } 26 27 private JSONObject orderReport() { 28 CompletableFuture<String> todayOrderCountFuture = orderService.todayOrderCount(); 29 CompletableFuture<String> todayTurnoverFuture = orderService.todayTurnover(); 30 CompletableFuture<String> totalTurnoverFuture = orderService.totalTurnover(); 31 32 JSONObject json = new JSONObject(); 33 34 todayOrderCountFuture.whenComplete((v, t) -> { 35 json.put("todayOrderCountFuture", v); 36 }); 37 todayTurnoverFuture.whenComplete((v, t) -> { 38 json.put("todayTurnoverFuture", v); 39 }); 40 totalTurnoverFuture.whenComplete((v, t) -> { 41 json.put("totalTurnoverFuture", v); 42 }); 43 44 CompletableFuture.allOf(todayOrderCountFuture, todayTurnoverFuture, totalTurnoverFuture) 45 .thenRun(() -> System.out.println("完成!!!!")) 46 .join(); 47 return json; 48 } 49 }
瀏覽器訪問:http://localhost:8080/order/report 執行結果截圖以下:瀏覽器
由於每一個OrderService的調用模擬都是耗時1秒,3個調用並行執行,最終耗時天然也是1秒。app