CompletableFuture是java8的新特性:異步編程。
直接上代碼(詳細(xì)說明在代碼中):
package com.example.java8.chapter11;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
/**
* 提醒:下面每個方法最后幾行注釋的代碼是此方法在執(zhí)行時,在console打印的內(nèi)容
*/
public class FutureTest {
public void delay(int second) {
long time = second * 1000;
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public String thing1() {
delay(1);
System.out.println("thing1:方法執(zhí)行中");
return "thing1返回值";
}
public Integer thing2() {
delay(2);
System.out.println("thing2:方法執(zhí)行中");
return 100;
}
public String thing3() {
delay(3);
System.out.println("thing3:方法執(zhí)行中");
return "thing3返回值";
}
public String thing4(String text) {
delay(4);
System.out.println("參數(shù):" + text);
System.out.println("thing4:方法執(zhí)行中");
return "thing4返回值";
}
/**有返回結(jié)果的異步執(zhí)行*/
@Test
public void test1() throws Exception {
// 1.異步執(zhí)行,重新起一個線程去執(zhí)行新的任務(wù)
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> thing1());
// 2.獲取異步執(zhí)行的結(jié)果,限定時間在2秒內(nèi)(避免無限期等待;如果超過2秒,就會拋出Timeout異常)
String text = future.get(2L, TimeUnit.SECONDS);
// 3.打印結(jié)果
System.out.println("結(jié)果:" + text);
// thing1:方法執(zhí)行中
// 結(jié)果:thing1返回值
}
/**無返回結(jié)果的異步執(zhí)行*/
@Test
public void test2() throws Exception {
// join方法是為了獲取結(jié)果;如果不關(guān)注結(jié)果,可以不調(diào)用join方法(異步線程也會執(zhí)行)
// get方法和join方法效果一樣;
// get(Long time) 帶參數(shù)的get方法表示設(shè)置超時,建議使用設(shè)置超時的get獲取異步執(zhí)行結(jié)果
CompletableFuture.runAsync(() -> thing1()).join();
// thing1:方法執(zhí)行中
}
@Test
public void test3() {
// 等待第一個異步執(zhí)行完畢后,得到異步執(zhí)行結(jié)果繼續(xù)執(zhí)行,沒有返回值
CompletableFuture<Void> accept = CompletableFuture.supplyAsync(() -> thing1())
.thenAccept(e -> System.out.println("包裝結(jié)果:" + e));
accept.join();
// thing1:方法執(zhí)行中
// 包裝結(jié)果:thing1返回值
}
@Test
public void test4() {
// 等待第一個方法執(zhí)行完畢,然后第二方法執(zhí)行完畢,接著處理方法1和方法2的結(jié)果,沒有返回值
CompletableFuture<Void> acceptBoth = CompletableFuture.supplyAsync(() -> thing1())
.thenAcceptBoth(CompletableFuture.supplyAsync(() -> thing3()), (e1, e2) -> System.out.println(e1 +" "+ e2));
acceptBoth.join();
// thing1:方法執(zhí)行中
// thing3:方法執(zhí)行中
// thing1返回值 thing3返回值
}
@Test
public void test5() {
// 等待第一個異步執(zhí)行完畢后,得到異步執(zhí)行結(jié)果繼續(xù)執(zhí)行,有返回值(和thenAccept相似,區(qū)別就是有返回值)
CompletableFuture<Integer> thenApply = CompletableFuture.supplyAsync(() -> thing1())
.thenApply((t) -> {
System.out.println(t);
return 999;
});
thenApply.join();
// thing1:方法執(zhí)行中
// thing1返回值
}
@Test
public void test6() {
// 等待第一個方法執(zhí)行完畢,然后第二方法執(zhí)行完畢,接著處理方法1和方法2的結(jié)果,有返回值(和thenAcceptBoth相似,區(qū)別就是有返回值)
CompletableFuture<String> thenCombine = CompletableFuture.supplyAsync(() -> thing1())
.thenCombine(CompletableFuture.supplyAsync(() -> thing2()), (e1, e2) -> {
System.out.println("e1:" + e1);
System.out.println("e2:" + e2);
return "java";
});
thenCombine.join();
// thing1:方法執(zhí)行中
// thing2:方法執(zhí)行中
// e1:thing1返回值
// e2:100
}
@Test
public void test7() {
// 異步方法1執(zhí)行完畢后,方法1的結(jié)果傳遞給方法2繼續(xù)執(zhí)行
CompletableFuture<String> thenCompose = CompletableFuture.supplyAsync(() -> thing1())
.thenCompose(e -> CompletableFuture.supplyAsync(() -> thing4(e)));
thenCompose.join();
// thing1:方法執(zhí)行中
// 參數(shù):thing1返回值
// thing4:方法執(zhí)行中
}
@Test
public void test8() {
// 異步方法1執(zhí)行完畢后,再執(zhí)行1個action
CompletableFuture.supplyAsync(() -> thing1()).thenRun(() -> System.out.println("執(zhí)行中")).join();
// thing1:方法執(zhí)行中
// 執(zhí)行中
}
@Test
public void test9() {
// 一個異步方法執(zhí)行完畢后,得到他的返回結(jié)果和異常信息進(jìn)一步處理,最后返回方法1返回結(jié)果
String join = CompletableFuture.supplyAsync(() -> thing1()).whenComplete((e1, e2) -> {
System.out.println("e1: 異步請求的結(jié)果:" + e1);
System.out.println("e2: 異常:" + e2);
}).join();
System.out.println(join);
// thing1:方法執(zhí)行中
// e1: 異步請求的結(jié)果:thing1返回值
// e2: 異常:null
// thing1返回值
}
@Test
public void test10() {
// 一個異步方法執(zhí)行完畢后,得到他的返回結(jié)果和異常信息進(jìn)一步處理,最后返回其他類型的結(jié)果
CompletableFuture<Integer> handle = CompletableFuture.supplyAsync(() -> thing1()).handle((e1, e2) -> {
System.out.println("e1: 異步請求的結(jié)果:" + e1);
System.out.println("e2: 異常:" + e2);
return 300;
});
Integer i = handle.join();
System.out.println(i);
// thing1:方法執(zhí)行中
// e1: 異步請求的結(jié)果:thing1返回值
// e2: 異常:null
// 300
}
}