この記事は、「新人クリエーションセレモニー」イベントに参加し、一緒にゴールドクリエーションの道を歩み始めました。
非同期を初期化する4つの方法
1.スレッドの継承2.Runnableの実装
3.Callable
インターフェースの実装+Future(jdk1.5以降、戻り結果を取得して例外を処理できます)
4.スレッドプール[ExecutorService](実際の開発で使用)
モード1、2:メインスレッドはスレッドの動作結果を取得できません。
モード3:メインスレッドはスレッドの操作結果を取得できますが、サーバー内のスレッドリソースを制御するのに役立ちません。サーバーリソースの枯渇につながる可能性があります。
モード4:スレッドプールのパフォーマンスは安定しており、リソースは制御され、実行結果も取得でき、例外をキャッチできます。
スレッドプールの7つのパラメーター:
- corePoolSize:[5]コアスレッドの数[(allowCoreThreadTimeOutがリサイクルされない限り)常に存在します];スレッドプール、作成後に5スレッドの準備ができていますThread thread = new Thread();開始されていません。thread.start();は、タスクがスレッドプールに送信された後にのみ実行されます。
- maximumPoolSize:[200]スレッドの最大数;制御リソース
- keepAliveTime:生き続ける時間。現在のスレッド数がコア数よりも多い場合。アイドル状態のスレッドを解放します(maximumPoolSize-corePoolSize)。スレッドが指定されたkeepAliveTimeより長くアイドル状態である限り。
- unit:時間の単位。
- BlockingQueue workQueue:ブロックキュー。タスクが多い場合は、現在のタスクがキューに入れられます。アイドル状態のスレッドがある限り、キューに戻り、新しいタスクを実行して実行を続行します。new LinedBlockingDeque <>():デフォルトは整数の最大値であり、メモリ不足が発生します
- threadFactory:スレッド作成ファクトリ
- RejectedExecutionHandlerハンドラー:ポリシー列を拒否し、キューがいっぱいの場合は、対応する拒否ポリシーを実行します7.1 DiscardOldestPolicy:新しいタスク が入った
ときに実行されない古いタスクを破棄 し ます7.4 DiscardPolicy:例外をスローせずに直接破棄します
作業順序:
- スレッドプールが作成され、コア数のコアスレッドの準備が整い、タスクを受け入れる準備が整います。
- コアがいっぱいになると、着信タスクはブロッキングキューに配置され、アイドル状態のコアはブロッキングキューに移動して、タスクを実行します。
- ブロッキングキューがいっぱいになると、実行のために新しいスレッドが直接開かれ、maximumはmaxで指定された数までしか開くことができません。
- maxがいっぱいになると、タスクはRejectedExecutionHandlerストラテジーで拒否されます。
- 最大実行が完了し、多くのアイドル時間があり、指定された時間keepAliveTimeの後、最大コアスレッドが解放されます
エグゼキュータ
- newCachedThreadPool()コアは0であり、すべてリサイクル可能です
- newFixedThreadPool()固定サイズcore=max;リサイクルできません
- 時限タスク用のnewScheduledThreadPllo()スレッドプール
- newSingleThreadExecutor()シングルスレッドスレッドプール、バックグラウンドはタスクを1つずつ実行します
1.非同期オブジェクトを作成します
CompletableFutureは4つの静的メソッドを提供します
//可以获取到返回值,可传入自定义线程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
//没有返回值,可传入自定义线程池
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
复制代码
テスト
public static ExecutorService service = Executors.newFixedThreadPool(10);
//没有返回值
CompletableFuture.runAsync(()->{
System.out.println("异步任务成功完成了");
},service);
//空入参只有返回值
CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
return "返回值";
}, service);
复制代码
2.計算完了時のコールバック方式
//上一个任务完成和上一个任务用同一个线程
public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
//交给线程池重新启动一个线程
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);
//任务执行完成后(只能感知)
public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
//感知异常同时修改返回值
public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn);
复制代码
テストコード
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
return 10;
}, service).whenComplete((res,excption)->{
//虽然能得到异常消息但是不能修改返回结果
System.out.println("异步任务成功完成了"+res+"或者异常:"+excption);
}).exceptionally(throwable ->{
//处理异常并可以数据修改返回值
return 0;
});
复制代码
3.ハンドルメソッド(例外が発生したときに処理して返す)
//和上一个任务使用同一个线程执行
public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn)
//默认线程池开启线程执行
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn)
//指定自己的线程池开启线程执行
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor)
复制代码
4.ハンドルテスト
//方法执行完成后的处理不论成功还是失败
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
return 10;
}, service).handle((res,thr)->{
//未出现异常 当然这里可以不写 为了掩饰
if(res!=null){
return 0;
}
//出现异常
if(thr!=null){
return 1;
}
return 0;
});
复制代码
5.スレッドのシリアル化方法(タスクBは、タスクAの実行結果の後でのみ実行できます)
//A-->B-->C 感知上一步结果并返回最后一次的结果
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn,Executor executor)
//B可以感知到A的返回值
public CompletableFuture<Void> thenAccept(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,
Executor executor)
//A->完成后(有Async开启新的线程没有就是和A一个线程)感知不到上一步的执行结果
public CompletableFuture<Void> thenRun(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action, Executor executor)
复制代码
テスト
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> {
//任务A
return 10;
}, service).thenRunAsync(() -> {
//感知不到 任务A的结果
},service);
复制代码
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> {
//任务A
return 10;
}, service).thenAcceptAsync((res) -> {
//可以感知到任务A的结果,但是不能返回数据
int i = res / 2;
},service);
复制代码
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//任务A
return 10;
}, service).thenApplyAsync((res) -> {
//返回值以最后一次返回为准
return 10 + res;
}, service);
复制代码
6.2つのタスクの組み合わせ-両方を完了する必要があります
以下三种方式 两个任务都必须完成,才触发该任务
//组合两个future,获取两个future 任务的返回结果,并返回当前任务的返回值
public <U,V> CompletableFuture<V> thenCombine(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn, Executor executor)
//组合两个future,获取两个future 任务的返回结果,然后处理任务,没有返回值。
public <U> CompletableFuture<Void> thenAcceptBoth(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action)
public <U> CompletableFuture<Void> thenAcceptBothAsync(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action)
public <U> CompletableFuture<Void> thenAcceptBothAsync(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action, Executor executor)
//组合两个future ,不需要获取future的结果,只需要两个 future处理完成后处理该任务
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor)
复制代码
テスト
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
//任务A
System.out.println(Thread.currentThread().getId());
System.out.println("任务一结束");
return 10/2;
}, service);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
//任务A
System.out.println(Thread.currentThread().getId());
System.out.println("任务二结束");
return "future02";
}, service);
//不能感知到结果
CompletableFuture<Void> future03void = future01.runAfterBothAsync(future02, () -> {
System.out.println("任务三执行结束");
}, service);
//可以感知获取到前两个任务结果
CompletableFuture<Void> future03No = future01.thenAcceptBothAsync(future02, (res1, res2) -> {
System.out.println("任务三执行结束");
}, service);
CompletableFuture<String> future03 = future01.thenCombineAsync(future02, (res1, res2) -> {
System.out.println("任务三执行结束");
return res1 + "-" + res2;
}, service);
复制代码
7.2つのタスクが1つずつ完了します
//两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值
public <U> CompletableFuture<U> applyToEither( CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T>other,Function<? super T, U> fn,Executor executor)
//两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值
public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor)
//两个任务有一个执行完成,不需要获取future的结果,处理任务 ,也没有返回值
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor)
复制代码
テスト
/**
* 两个任务有一个完成就执行三
*
*/
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
//任务A
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getId());
System.out.println("任务一结束");
return 10/2;
}, service);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
//任务A
System.out.println(Thread.currentThread().getId());
System.out.println("任务二结束");
return "future02";
}, service);
//不感知结果,自己也没有返回值
future01.runAfterEitherAsync(future02,()->{
System.out.println("任务三执行结束");
},service);
//感知到结果,自己没有返回值
future01.acceptEitherAsync(future02,(res)->{
//感知到线程已经处理完成的结果
System.out.println("任务三执行结束"+res);
},service);
//感知到结果并返回自己的返回值
CompletableFuture<String> stringCompletableFuture = future01.applyToEitherAsync(future02, res -> {
return "任务三结果" + res;
}, service);
复制代码
8.マルチタスクの組み合わせ
//等待所有任务完成
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
//只要有一个任务完成
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
复制代码
テスト
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
//任务A
System.out.println(Thread.currentThread().getId());
System.out.println("任务一结束");
return 10/2;
}, service);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
//任务A
System.out.println(Thread.currentThread().getId());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务二结束");
return "future02";
}, service);
//此方法是阻塞式等待不建议在这使用
//future01.get();
//future02.get();
//等待所有任务完成不会阻塞
CompletableFuture<Void> allOf= CompletableFuture.allOf(future01, future02);
//等待所有的都完成(两个任务同时执行)
allOf.get();
log.info("end");
System.out.println(future02.get()+""+future01.get());
//只有一个完成
CompletableFuture<Object> anyOf= CompletableFuture.anyOf(future01, future02);
anyOf.get();
System.out.println(anyOf.get());
复制代码