package future;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author XRZ
* @date 2020/6/15 18:05
* @Description :
*/
public class FutureTest {
private ThreadPoolExecutor executor;
@Before
public void init(){
executor = new ThreadPoolExecutor(
2,
4,
30,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>()
);
}
@After
public void waitAsync() throws InterruptedException {
Thread.sleep(5000);
}
@Test
public void cretae_CompletableFuture() throws Exception {
/**
* CompletableFuture.runAsync(Runnable runnable);
*/
CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName()+"======>無返回值異步線程,使用JDK默認線程池執行:ForkJoinPool.commonPool()");
});
/**
* CompletableFuture.runAsync(Runnable runnable, Executor executor);
*/
CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName()+"======>無返回值異步線程,使用指定線程池執行");
},executor);
/**
* CompletableFuture.supplyAsync(Supplier<U> supplier);
*/
CompletableFuture<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {
return Thread.currentThread().getName()+"======>有返回值異步線程,使用JDK默認線程池執行:ForkJoinPool.commonPool()";
});
System.out.println(completableFuture1.get());
/**
* CompletableFuture.supplyAsync(Supplier<U> supplier, Executor executor)
*/
CompletableFuture<String> completableFuture2 = CompletableFuture.supplyAsync(() -> {
return Thread.currentThread().getName() + "======>有返回值異步線程,使用指定線程池執行";
}, executor);
System.out.println(completableFuture2.get());
// ForkJoinPool.commonPool-worker-1======>無返回值異步線程,使用JDK默認線程池執行:ForkJoinPool.commonPool()
// pool-1-thread-1======>無返回值異步線程,使用指定線程池執行
// ForkJoinPool.commonPool-worker-1======>有返回值異步線程,使用JDK默認線程池執行:ForkJoinPool.commonPool()
// pool-1-thread-2======>有返回值異步線程,使用指定線程池執行
}
@Test
public void get_CompletableFuture() throws Exception {
/**
* CompletableFuture.get() 獲取結果
*/
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "result");
System.out.println(future1.get());
/**
* CompletableFuture.getNow(T valueIfAbsent) 獲取結果,如果在執行getNow的時候,還未返回結果或者拋了異常,返回valueIfAbsent
*/
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "result");
Thread.sleep(500);
System.out.println(future2.getNow("res"));
/**
* CompletableFuture.get(long timeout, TimeUnit unit) 獲取結果,如果超過等待時間,throw TimeoutException
*/
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "result";
});
System.out.println(future3.get(1,TimeUnit.SECONDS));
// result
// result
//
// java.util.concurrent.TimeoutException
}
@Test
public void complete_CompletableFuture() throws Exception {
/**
* complete(T t) :結束異步線程,返回T(多次調用以第一次爲準)
*/
CompletableFuture<String> completableFuture1 = CompletableFuture.supplyAsync(() -> "RESULT");
completableFuture1.complete("結束異步線程,返回指定結果");
System.out.println(completableFuture1.get());
/**
* completeExceptionally(Throwable ex) :結束異步線程,返回一個異常
*/
CompletableFuture<String> completableFuture2 = CompletableFuture.supplyAsync(() -> "RESULT");
// Thread.sleep(1000);
completableFuture2.completeExceptionally(new RuntimeException("結束異步線程,返回自定義異常"));
System.out.println(completableFuture2.get());
/**
* 如果異步線程比主線程先執行完成,則正常返回,complete/completeExceptionally 失效
*/
// 結束異步線程,返回指定結果
//
// java.util.concurrent.ExecutionException: java.lang.RuntimeException: 結束異步線程,返回自定義異常
}
@Test
public void thenApply_CompletableFuture() throws Exception{
/**
* 結果轉換 T -> U
* thenApply(Function<? super T,? extends U> fn)
* thenApplyAsync(Function<? super T,? extends U> fn)
* thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)
*/
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> "RESULT")
.thenApply(res -> res + "Convert")
.thenApply(String::length);
System.out.println(future.get());
// 13
}
@Test
public void whenComplete_CompletableFuture() throws Exception{
/**
* 對結果的處理
* whenComplete(BiConsumer<? super T,? super Throwable> action)
* whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
* whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
*/
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 1/0)
.whenComplete((res, e) -> {
System.out.println("RESULT:"+res);
System.out.println("異常信息:"+e);
});
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 1/1)
.whenComplete((res, e) -> {
System.out.println("RESULT:"+res);
System.out.println("異常信息:"+e);
});
System.out.println(future2.get());
// RESULT:null
// 異常信息:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
// RESULT:1
// 異常信息:null
// 1
}
@Test
public void handle_CompletableFuture() throws Exception{
/**
* 對結果的處理並且轉換
* handle(BiFunction<? super T, Throwable, ? extends U> fn)
* handleAsync(BiFunction<? super T, Throwable, ? extends U> fn)
* handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor)
*/
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> 1/1)
.handle((res, e) -> {
System.out.println("RESULT:"+res);
System.out.println("異常信息:"+e);
return "RESULT";
});
System.out.println(future2.get());
// RESULT:1
// 異常信息:null
// RESULT
}
@Test
public void thenAccept_CompletableFuture() throws Exception{
/**
* thenAccept(Consumer<? super T> action)
* thenAcceptAsync(Consumer<? super T> action)
* thenAcceptAsync(Consumer<? super T> action, Executor executor)
*/
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "RESULT")
.thenAccept(res -> {
System.out.println("消費結果且無返回:"+res);
});
System.out.println(future.get()); //null
// 消費結果且無返回:RESULT
// null
}
@Test
public void thenRun_CompletableFuture() throws Exception{
/**
* thenRun(Runnable action)
* thenRunAsync(Runnable action)
* thenRunAsync(Runnable action, Executor executor)
*/
CompletableFuture.runAsync(() -> {
System.out.println("異步線程方法執行1");
}).thenRun(() -> {
System.out.println("異步線程方法執行2");
}).thenRun(() -> {
System.out.println("異步線程方法執行3");
});
// 異步線程方法執行1
// 異步線程方法執行2
// 異步線程方法執行3
}
}