著者:王栄私はQiafu
オリジナル: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を使用しないのはなぜですか。ここに注意があります。すべてのサブタスクが実行される時点を取得する必要があります。この時点の後で、結果をカプセル化して返すことができます。スレッドには満足する方法がありません。ここでは、parallelStreamと機能インターフェースがシーンにあります。
java8-lambda式の特性の1つは、機能インターフェースと組み合わせて使用されます。
Java 8には4つのコア機能インターフェースが組み込まれています。
1.コンシューマー:コンシューマーインターフェイスvoid accept(T t);
2.サプライヤー:インターフェースT get();を提供します。
3. Function <T、R>:機能インターフェースR apply(T t);
4.述語:アサーションタイプインターフェースブール値test(T t);
これら4つのコア機能インターフェースの下には多くのサブインターフェースがあり、基本的に日常のプロジェクトのニーズを満たすことができます。。コードに直接移動します。
ここでは、パラメーターも戻り値もないインターフェースである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) + "毫秒");
}
実行の結果、4つのサブタスクがすべて並列であるため、効率は直接3倍になり、サブタスクが多いほど、改善効果が明確になります。
数据汇总开始
查询在线人数 耗时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、分散キャッシュ、データ構造など。