併發程式設計--常用方法以及CompletableFuture
常用方法
-
宣告一個ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
-
ExecutorService方式:execute方法 new Runnable() 這樣可以非同步的執行Runnable裡面的方法。
//非同步方式一
@Override
public void get1() {
System.out.println("非同步1");
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
get4();
}
});
}
- 使用註解方式(需要spring掃描) 啟動類打上@EnableAsync註解開啟非同步
- 非同步方法加上@Async 標識這是一個非同步方法
- 控制層呼叫該方法,就會非同步執行
CompletableFuture常用方法
- CompletableFuture類實現了CompletionStage和Future介面。Future是Java 5新增的類,用來描述一個非同步計算的結果,
- 但是獲取一個結果時方法較少,要麼通過輪詢isDone,確認完成後,呼叫get()獲取值,要麼呼叫get()設定一個超時時間。
- 但是這個get()方法會阻塞住呼叫執行緒,這種阻塞的方式顯然和我們的非同步程式設計的初衷相違背。
- 為了解決這個問題,JDK吸收了guava的設計思想,加入了Future的諸多擴充套件功能形成了CompletableFuture。
- /*
已Async結尾的方法都是可以非同步執行的,如果指定了執行緒池,會在指定的執行緒池中執行,如果沒有指定,預設會在ForkJoinPool.commonPool()中執行。
關鍵的入參只有一個Function,它是函式式介面,所以使用Lambda表示.
/
/*- 入參是上一個階段計算後的結果,返回值是經過轉化後結果。
- public CompletionStage thenApply(Function<? super T,? extends U> fn);
- public CompletionStage thenApplyAsync(Function<? super T,? extends U> fn);
- public CompletionStage thenApplyAsync(Function<? super T,? extends U> fn,Executor executor);
*/
@Test
public void thenApply() {
String result = CompletableFuture.supplyAsync(() -> "hello").thenApply(s -> s + " world").join();
System.out.println(result);
}
@Test
public void thenApplyAsync() {
String result = CompletableFuture.supplyAsync(() -> "hello").thenApplyAsync(s -> s + " world").join();
System.out.println(result);
}
@Test
public void thenApplyAsyncAndExecutor() {
String result = CompletableFuture.supplyAsync(() -> "hello").thenApplyAsync(s -> s + " world", newCachedThreadPool).join();
System.out.println(result);
}
/**
* thenAccept是針對結果進行消耗,因為他的入參是Consumer,有入參無返回值。
* public CompletionStage thenAccept(Consumer<? super T> action);
* public CompletionStage thenAcceptAsync(Consumer<? super T> action);
* public CompletionStage thenAcceptAsync(Consumer<? super T> action,Executor executor);
*/
@Test
public void thenAccept() {
CompletableFuture.supplyAsync(() -> "hello").thenAccept(s -> System.out.println(s + " world"));
}
/**
* 對上一步的計算結果不關心,執行下一個操作。
* public CompletionStage thenRun(Runnable action);
* public CompletionStage thenRunAsync(Runnable action);
* public CompletionStage thenRunAsync(Runnable action,Executor executor);
*/
@Test
public void thenRun() {
CompletableFuture.supplyAsync(() -> {
int i=1+1;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}).thenRunAsync(() -> System.out.println("hello world"),newCachedThreadPool);
while (true) {
}
}
@Test
public void thenRunAsync() {
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}).thenRun(() -> System.out.println("hello world"));
while (true) {
}
}
@Test
public void thenRunAsyncAndExecutor() {
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}).thenRunAsync(() -> System.out.println("hello world"), newCachedThreadPool);
while (true) {
}
}
/**
* 結合兩個CompletionStage的結果,進行轉化後返回
* public <U,V> CompletionStage thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
* public <U,V> CompletionStage thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
* public <U,V> CompletionStage thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor);
* 它需要原來的處理返回值,並且other代表的CompletionStage也要返回值之後,利用這兩個返回值,進行轉換後返回指定型別的值。
*/
@Test
public void thenCombine() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}).thenCombine(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "world";
}), (s1, s2) -> s1 + " " + s2).join();
System.out.println(result);
}
/**
* 結合兩個CompletionStage的結果,進行消耗
* public CompletionStage thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
* public CompletionStage thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
* public CompletionStage thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor);
* 它需要原來的處理返回值,並且other代表的CompletionStage也要返回值之後,利用這兩個返回值,進行消耗。
*/
@Test
public void thenAcceptBoth() {
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}).thenAcceptBoth(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "world";
}), (s1, s2) -> System.out.println(s1 + " " + s2));
while (true) {
}
}
/**
* 在兩個CompletionStage都執行完執行。
* public CompletionStage runAfterBoth(CompletionStage<?> other,Runnable action);
* public CompletionStage runAfterBothAsync(CompletionStage<?> other,Runnable action);
* public CompletionStage runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor);
* 不關心這兩個CompletionStage的結果,只關心這兩個CompletionStage執行完畢,之後在進行操作(Runnable)。
*/
@Test
public void runAfterBoth() {
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s1";
}).runAfterBothAsync(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s2";
}), () -> System.out.println("hello world"));
while (true) {
}
}
/**
* 兩個CompletionStage,誰計算的快,我就用那個CompletionStage的結果進行下一步的轉化操作。
* public CompletionStage applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn);
* public CompletionStage applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn);
* public CompletionStage applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor);
* 碰到有兩種渠道完成同一個事情,所以就可以呼叫這個方法,找一個最快的結果進行處理。
*/
@Test
public void applyToEither() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s1";
}).applyToEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello world";
}), s -> s).join();
System.out.println(result);
}
/**
* 兩個CompletionStage,任何一個完成了都會執行下一步的操作(Runnable)
* public CompletionStage runAfterEither(CompletionStage<?> other,Runnable action);
* public CompletionStage runAfterEitherAsync(CompletionStage<?> other,Runnable action);
* public CompletionStage runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor);
*/
@Test
public void runAfterEither() {
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s1";
}).runAfterEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s2";
}), () -> System.out.println("hello world"));
while (true) {
}
}
/**
* 當執行時出現了異常,可以通過exceptionally進行補償
* public CompletionStage exceptionally(Function<Throwable, ? extends T> fn);
*/
@Test
public void exceptionally() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (1 == 1) {
throw new RuntimeException("測試一下異常情況");
}
return "s1";
}).exceptionally(e -> {
System.out.println(e.getMessage());
return "hello world";
}).join();
System.out.println(result);
}
/**
* 當執行完成時,對結果的記錄。這裡的完成時有兩種情況,一種是正常執行,返回值。另外一種是遇到異常丟擲造成程式的中斷。
* 這裡為什麼要說成記錄,因為這幾個方法都會返回CompletableFuture,
* 當Action執行完畢後它的結果返回原始的CompletableFuture的計算結果或者返回異常。所以不會對結果產生任何的作用。
* public CompletionStage whenComplete(BiConsumer<? super T, ? super Throwable> action);
* public CompletionStage whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);
* public CompletionStage whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action,Executor executor);
*/
@Test
public void whenComplete() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (1 == 1) {
throw new RuntimeException("測試一下異常情況");
}
return "s1";
}).whenComplete((s, t) -> {
System.out.println(s);
System.out.println(t.getMessage());
}).exceptionally(e -> {
System.out.println(e.getMessage());
return "hello world";
}).join();
System.out.println(result);
}
//這裡也可以看出,如果使用了exceptionally,就會對最終的結果產生影響,它沒有口子返回如果沒有異常時的正確的值,這也就引出下面我們要介紹的handle。
/**
* 執行完成時,對結果的處理。這裡的完成時有兩種情況,一種是正常執行,返回值。另外一種是遇到異常丟擲造成程式的中斷。
* public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);
* public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
* public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Executor executor);
*/
//出現異常時
@Test
public void handleHasException() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//出現異常
if (1 == 1) {
throw new RuntimeException("測試一下異常情況");
}
return "s1";
}).handle((s, t) -> {
if (t != null) {
return "hello world";
}
return s;
}).join();
System.out.println(result);
}
//未出現異常時
@Test
public void handle() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s1";
}).handle((s, t) -> {
if (t != null) {
return "hello world";
}
return s;
}).join();
System.out.println(result);
}
//方法非同步執行
@Test
public void test2() throws Exception {
System.out.println("main函式開始執行");
ExecutorService executor = Executors.newFixedThreadPool(2);
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {
@Override
public Integer get() {
System.out.println("===task start===");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("===task finish===");
return 3;
}
}, executor);
future.thenAccept(e -> System.out.println(e));
System.out.println("main函式執行結束");
}
相關文章
- java併發程式設計學習15--CompletableFuture(二)Java程式設計
- c++11併發程式設計歷程(15):併發設計以及併發設計資料結構的思考C++程式設計資料結構
- 非同步程式設計CompletableFuture實現高併發系統優化之請求合併非同步程式設計優化
- 非同步程式設計 CompletableFuture非同步程式設計
- 併發程式設計程式設計
- 併發程式設計Thread的常用API有哪些?程式設計threadAPI
- 【Java併發程式設計】併發程式設計大合集-值得收藏Java程式設計
- 併發程式設計之 wait notify 方法剖析程式設計AI
- 併發程式設計 —— ConcurrentHashMap size 方法原理分析程式設計HashMap
- ?【Java技術專區】「併發程式設計專題」教你如何使用非同步神器CompletableFutureJava程式設計非同步
- Java8 CompletableFuture 程式設計Java程式設計
- 非同步程式設計利器:CompletableFuture非同步程式設計
- Go 併發程式設計 - 併發安全(二)Go程式設計
- Golang 併發程式設計Golang程式設計
- 併發程式設計(四)程式設計
- 併發程式設計(二)程式設計
- java 併發程式設計Java程式設計
- 併發程式設計13程式設計
- golang併發程式設計Golang程式設計
- Java併發程式設計Java程式設計
- Go 併發程式設計Go程式設計
- shell併發程式設計程式設計
- Scala併發程式設計程式設計
- 併發程式設計 synchronized程式設計synchronized
- java併發程式設計 --併發問題的根源及主要解決方法Java程式設計
- 併發程式設計和並行程式設計程式設計並行行程
- JUC併發系列(八):併發程式設計常用輔助類CountDownLatch與CyclicBarrier(手敲程式碼示例)程式設計CountDownLatch
- Java併發程式設計-鎖及併發容器Java程式設計
- 併發程式設計之:JUC併發控制工具程式設計
- Java併發系列—併發程式設計挑戰Java程式設計
- 【Java併發程式設計】一、為什麼需要學習併發程式設計?Java程式設計
- Java併發程式設計 - 第十一章 Java併發程式設計實踐Java程式設計
- CompletableFuture 組合式非同步程式設計非同步程式設計
- java-併發程式設計Java程式設計
- 併發程式設計前傳程式設計
- 併發程式設計導論程式設計
- C# 併發程式設計C#程式設計
- Java併發程式設計-CASJava程式設計