
作者:我恰芙蓉王
原文:https://www.cnblogs.com/-tang/p/13283216.html
業務場景
在很多專案中,都有類似資料匯總的業務場景,查詢今日注冊會員數,在線會員數,訂單總金額,支出總金額等,,,這些業務通常都不是存在同一張表中,我們需要依次查詢出來然后封裝成所需要的物件回傳給前端,那么在此程序中,就可以把這個介面中“大任務”拆分成N個小任務,異步執行這些小任務,等到最后一個小任務執行完,把所有任務的執行結果封裝到回傳結果中,統一回傳到前端展示,
同步執行
首先看看同步執行的代碼
public class Test {
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
class Result {
/**
* 在線人數
*/
Integer onlineUser;
/**
* 注冊人數
*/
Integer registered;
/**
* 訂單總額
*/
BigDecimal orderAmount;
/**
* 支出總額
*/
BigDecimal outlayAmount;
}
@org.junit.Test
public void collect() {
System.out.println("資料匯總開始");
long startTime = System.currentTimeMillis();
Integer onlineUser = queryOnlineUser();
Integer registered = queryRegistered();
BigDecimal orderAmount = queryOrderAmount();
BigDecimal outlayAmount = queryOutlayAmount();
Result result = new Result(onlineUser, registered, orderAmount, outlayAmount);
long endTime = System.currentTimeMillis();
System.out.println("獲取匯總資料結束,result = " + result);
System.out.println("總耗時 = " + (endTime - startTime) + "毫秒");
}
public Integer queryOnlineUser() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查詢在線人數 耗時2秒");
return 10;
}
public Integer queryRegistered() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查詢注冊人數 耗時2秒");
return 10086;
}
public BigDecimal queryOrderAmount() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查詢訂單總額 耗時3秒");
return BigDecimal.valueOf(2000);
}
public BigDecimal queryOutlayAmount() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查詢支出總額 耗時3秒");
return BigDecimal.valueOf(1000);
}
}
執行時長想必大家都能夠想得到,理所應當是10秒以上
資料匯總開始
查詢在線人數 耗時2秒
查詢注冊人數 耗時2秒
查詢訂單總額 耗時3秒
查詢支出總額 耗時3秒
獲取匯總資料結束,result = Test.Result(onlineUser=10, registered=10086, orderAmount=2000, outlayAmount=1000)
總耗時 = 10008毫秒
異步執行
下面換成異步執行,用java8的parallelStream(并行流),這里為什么不用Thread呢,這里有一個注意點,我們需要獲取所有所有子任務執行完的時間點,在這個時間點之后才能將結果封裝回傳,Thread沒有辦法滿足,這里parallelStream和函式式介面就登場了,
java8的特性之一 —— lambda運算式,就是配合函式式介面使用的,
java8內置了四大核心函式式介面:
1、Consumer
2、Supplier
3、Function<T,R> : 函式型介面 R apply(T t);
4、Predicate
這四大核心函式式介面其下還有很多子介面,基本上能滿足日常專案所用,這里扯遠了,, 直接上代碼,
這里我們需要使用的是Runable介面,是無參無回傳值的一個介面,在實際場景中,可能有時間范圍之類的查詢引數的,則可以根據不同業務使用不同的介面,這種方式也可以用Future介面去實作,有興趣的可以試一試,這里就不多做敘述了,
@org.junit.Test
public void collect() {
System.out.println("資料匯總開始");
long startTime = System.currentTimeMillis();
Result result = new Result();
List<Runnable> taskList = new ArrayList<Runnable>() {
{
add(() -> result.setOnlineUser(queryOnlineUser()));
add(() -> result.setRegistered(queryRegistered()));
add(() -> result.setOrderAmount(queryOrderAmount()));
add(() -> result.setOutlayAmount(queryOutlayAmount()));
}
};
taskList.parallelStream().forEach(v -> v.run());
long endTime = System.currentTimeMillis();
System.out.println("獲取匯總資料結束,result = " + result);
System.out.println("總耗時 = " + (endTime - startTime) + "毫秒");
}
執行結果,由于四個子任務都是并行的,效率直接提升了三倍,如果子任務越多的話提升效果越明顯,
資料匯總開始
查詢在線人數 耗時2秒
查詢注冊人數 耗時2秒
查詢訂單總額 耗時3秒
查詢支出總額 耗時3秒
獲取匯總資料結束,result = Test.Result(onlineUser=10, registered=10086, orderAmount=2000, outlayAmount=1000)
總耗時 = 3079毫秒
總結
1.parallelStream是異步編程的好幫手,在使用程序中一定要注意執行緒安全的問題,
2.以上這種方式只能用在沒有事務的業務中,因為在多執行緒中,事務是不共享的,
最后
私信回復 資料 領取一線大廠Java面試題總結+
阿里巴巴泰山手冊+各知識點學習思維導+一份300頁pdf檔案的Java核心知識點總結!
這些資料的內容都是面試時面試官必問的知識點,篇章包括了很多知識點,其中包括了有基礎知識、Java集合、JVM、多執行緒并發、spring原理、微服務、Netty 與RPC 、Kafka、日記、設計模式、Java演算法、資料庫、Zookeeper、分布式快取、資料結構等等,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/139420.html
標籤:Java
上一篇:不知道取啥標題=-=
