JAva 8同時プログラミング実戦-part 1
5795 ワード
技術バージョン
jdk: 1.8
前言
ネット上の投稿は千万で、私たちも一緒に冷たいご飯を炒めます.CompletableFutureは非同期プログラミングを構築するための基礎であり、同時にFutureとCompletionStageから受け継がれています.CompletionStageというインタフェースはpromiseで、この計算が最終的に完成することを示しています.
Futureの不足
1.操作完了e.g.を手動で設定することはできません.個別のスレッドを開いてrpcでインタフェースを調整していくつかのデータを返します.下流のインタフェースが切れた場合、前回キャッシュしたデータを返すことで手動で完了したいと思っています.この場合、Futureはこのようなapiサポートを持っていません.2.ブロック式の操作Futureの戻り結果e.gは、結果が利用可能になった場合、Futureは自発的に通知しません.get()メソッドを呼び出して結果を返すのを待つしかありません.Futureにコールバックを設定することはできません.構造が使用可能なときに自動的にコールバックを呼び出します.3.複数のFutureはチェーン呼び出しe.gを行うことができず、例えば2つの時間のかかる計算(A,B)があり、彼らは依存関係があり、A計算が完了すると、Bに伝達して計算を継続する必要がある.Futureでは非同期のフロー計算呼び出しはサポートされていません.4.複数のFuture e.gの組み合わせはサポートされていません.例えば、5つの同時サポートされているFutureがあります.私たちは彼らがすべて実行した後、追加の操作をしたいと思っています.Futureはサポートされていません.5.異常処理Future apiが異常処理を提供していないメカニズム
ケースの開始
最も単純な非同期
Step 1最も簡単な方法でCompletableFutureを作成します.step 2がなければ、step 3にあるget()メソッドは計算が完了していないため、ブロックされ続けます.step 4の複数回の呼び出しは無効です.すなわち、step 5は無効です.
runAsync()で非同期計算を行い、メソッドを変更してCompletableFutureを返します.
サンプルコード
これはjunitの中で行われるので、実行が完了するのを待つ必要があります.待つ方法は2種類あります:step 1とstep 2. get()メソッドを呼び出す必要があると勘違いしないでください. この方法には2つのリロード方法がある
メソッド1はForkJoinPoolのスレッドプールを使用し,メソッド2はカスタムスレッドプールに転送できる.
supplyAsync()は非同期計算を行い、戻り結果がある
サンプルコード
依然として2つのリロード方法があり、詳しくはapi、スレッドプールの説明を参照してください.
非同期CompletableFutureの構築
上のget()はブロックされています.彼は実行が完了するまでブロックします.これが最初に私たちが言ったFutureの不足です.これは私たちが望んでいるものではありません.私たちが必要なのはコールバックを設定して、実行が完了したら自動的に呼び出すことができます.次に、これらの方法を見てみましょう.1.thenApply()方法は、参照としてFunctionを受け入れ、同時に参照付きCompletableFutureに戻ります. サンプルコード
supplyAsyncの実行が完了すると、thenApply()メソッドを自動的に呼び出してthenApply内の論理を実行するスレッドと、supplyAsync論理を実行するスレッドは同じである.
2.thenAccept()は、CompletableFutureを返します.パラメータはConsumerサンプルコードです.まず非同期でデータを取得し、完了したら消費します.
3.thenRun()は、CompletableFutureを返します.パラメータはRunnableです.前のステップの戻り結果(戻り結果がある場合)のサンプルコードにアクセスできません.
この3つの方法はいずれも他の2つの接尾辞がAsyncのリロード方法であり,thenApplyを例にとると
Method 1はメソッド内部でForkJoinPool.commonPool()を使用していますが、テスト中にthenApplyAsyncを実行するロジックとsupplyAsyncを実行するスレッドが同じであることがわかり、またオンラインプールで同じものを手に入れたと推測されますが、あいにくですね...method 2は伝達されたexecutorを使用して実行しています
未完待续....
微信の公衆番号に注目してください. ぎせいプログラマ
jdk: 1.8
前言
ネット上の投稿は千万で、私たちも一緒に冷たいご飯を炒めます.CompletableFutureは非同期プログラミングを構築するための基礎であり、同時にFutureとCompletionStageから受け継がれています.CompletionStageというインタフェースはpromiseで、この計算が最終的に完成することを示しています.
Futureの不足
1.操作完了e.g.を手動で設定することはできません.個別のスレッドを開いてrpcでインタフェースを調整していくつかのデータを返します.下流のインタフェースが切れた場合、前回キャッシュしたデータを返すことで手動で完了したいと思っています.この場合、Futureはこのようなapiサポートを持っていません.2.ブロック式の操作Futureの戻り結果e.gは、結果が利用可能になった場合、Futureは自発的に通知しません.get()メソッドを呼び出して結果を返すのを待つしかありません.Futureにコールバックを設定することはできません.構造が使用可能なときに自動的にコールバックを呼び出します.3.複数のFutureはチェーン呼び出しe.gを行うことができず、例えば2つの時間のかかる計算(A,B)があり、彼らは依存関係があり、A計算が完了すると、Bに伝達して計算を継続する必要がある.Futureでは非同期のフロー計算呼び出しはサポートされていません.4.複数のFuture e.gの組み合わせはサポートされていません.例えば、5つの同時サポートされているFutureがあります.私たちは彼らがすべて実行した後、追加の操作をしたいと思っています.Futureはサポートされていません.5.異常処理Future apiが異常処理を提供していないメカニズム
ケースの開始
最も単純な非同期
@Test
public void test1() throws ExecutionException, InterruptedException {
CompletableFuture completableFuture = new CompletableFuture<>(); //step1
new Thread(new CompleteFutureTask(completableFuture)).start(); //step2
String result = completableFuture.get(); //step3
System.out.println(Thread.currentThread().getName() + " get result:" + result);
}
class CompleteFutureTask implements Runnable {
CompletableFuture completableFuture;
public CompleteFutureTask(CompletableFuture completableFuture) {
this.completableFuture = completableFuture;
}
@Override
public void run() {
MixAll.simulateComputeCost();
System.out.println(Thread.currentThread().getName() + " will complete future:" + completableFuture);
completableFuture.complete("hello completableFuture"); //step4
//completableFuture.complete("hello completableFuture"); //step5
}
}
Step 1最も簡単な方法でCompletableFutureを作成します.step 2がなければ、step 3にあるget()メソッドは計算が完了していないため、ブロックされ続けます.step 4の複数回の呼び出しは無効です.すなわち、step 5は無効です.
runAsync()で非同期計算を行い、メソッドを変更してCompletableFutureを返します.
サンプルコード
@Test
public void runAsyncTest() throws ExecutionException, InterruptedException {
CompletableFuture cf = CompletableFuture.runAsync(() -> {
MixAll.simulateComputeCost();
System.out.println(Thread.currentThread().getName() + " runAsyncTest...................");
});
cf.get(); //step1
//MixAll.simulateComputeCost(8); //step2
}
これはjunitの中で行われるので、実行が完了するのを待つ必要があります.待つ方法は2種類あります:step 1とstep 2. get()メソッドを呼び出す必要があると勘違いしないでください. この方法には2つのリロード方法がある
public static CompletableFuture runAsync(Runnable runnable)
public static CompletableFuture runAsync(Runnable runnable,Executor executor)
メソッド1はForkJoinPoolのスレッドプールを使用し,メソッド2はカスタムスレッドプールに転送できる.
supplyAsync()は非同期計算を行い、戻り結果がある
サンプルコード
@Test
public void supplyAsyncTest() throws ExecutionException, InterruptedException {
CompletableFuture cf = CompletableFuture.supplyAsync(() -> {
MixAll.simulateComputeCost();
MixAll.printWithThread(" will return something");
return "hello supplyAsync";
});
String data = cf.get();
MixAll.printWithThread(" get data:" + data);
}
依然として2つのリロード方法があり、詳しくはapi、スレッドプールの説明を参照してください.
非同期CompletableFutureの構築
上のget()はブロックされています.彼は実行が完了するまでブロックします.これが最初に私たちが言ったFutureの不足です.これは私たちが望んでいるものではありません.私たちが必要なのはコールバックを設定して、実行が完了したら自動的に呼び出すことができます.次に、これらの方法を見てみましょう.1.thenApply()方法は、参照としてFunctionを受け入れ、同時に参照付きCompletableFutureに戻ります. サンプルコード
@Test
public void thenApplyTest() throws ExecutionException, InterruptedException {
CompletableFuture cf = CompletableFuture
.supplyAsync(() -> {
MixAll.simulateComputeCost();
MixAll.printWithThread(" will return something");
return "hello supplyAsync";
})
.thenApply(info -> {
MixAll.simulateComputeCost();
MixAll.printWithThread(" will return something");
return "thenApply|" + info;
});
String data = cf.get();
MixAll.printWithThread(" get>>" + data);
}
supplyAsyncの実行が完了すると、thenApply()メソッドを自動的に呼び出してthenApply内の論理を実行するスレッドと、supplyAsync論理を実行するスレッドは同じである.
2.thenAccept()は、CompletableFutureを返します.パラメータはConsumerサンプルコードです.まず非同期でデータを取得し、完了したら消費します.
@Test
public void thenAcceptTest() {
CompletableFuture.supplyAsync(() -> UserService.Instance.getUser(12))
.thenAccept(user -> MixAll.printWithThread(" thenAccept get userName:" + user.getName()));
//
MixAll.simulateComputeCost(8);
}
3.thenRun()は、CompletableFutureを返します.パラメータはRunnableです.前のステップの戻り結果(戻り結果がある場合)のサンプルコードにアクセスできません.
@Test
public void thenRunTest() {
long start = System.currentTimeMillis();
CompletableFuture
.runAsync(() -> UserService.Instance.getUser(12))
.thenRun(() -> MixAll.printWithThread(" thenRun cost:" + (System.currentTimeMillis() - start) + "ms"));
//
MixAll.simulateComputeCost(8);
}
この3つの方法はいずれも他の2つの接尾辞がAsyncのリロード方法であり,thenApplyを例にとると
thenApplyAsync(Function super T,? extends U> fn) //method1
thenApplyAsync(Function super T,? extends U> fn, Executor executor) //method2
Method 1はメソッド内部でForkJoinPool.commonPool()を使用していますが、テスト中にthenApplyAsyncを実行するロジックとsupplyAsyncを実行するスレッドが同じであることがわかり、またオンラインプールで同じものを手に入れたと推測されますが、あいにくですね...method 2は伝達されたexecutorを使用して実行しています
未完待续....
微信の公衆番号に注目してください. ぎせいプログラマ