CompletableFuture使用
package com.xiaobu.juc.CompeletableFuture;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.util.StopWatch;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.stream.Collectors;
@Slf4j
public class CompletableFutureTest {
public static ExecutorService fixedExecutorService = Executors.newFixedThreadPool(5);
StopWatch stopWatch = new StopWatch();
public static String getUserInfo() {
try {
TimeUnit.SECONDS.sleep(1L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "userInfo";
}
public static String getSkillInfo() {
try {
TimeUnit.SECONDS.sleep(3L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "skillInfo";
}
@Before
public void before() {
log.info("start");
stopWatch.start();
}
@After
public void after() {
stopWatch.stop();
log.info("end");
System.out.printf("耗时= %sS", stopWatch.getTotalTimeSeconds());
}
@SneakyThrows
@Test
public void testSupplyAsync() {
CompletableFuture<String> completableUserInfoFuture = CompletableFuture.supplyAsync(CompletableFutureTest::getUserInfo, fixedExecutorService);
TimeUnit.SECONDS.sleep(2L);
CompletableFuture<String> completableSkillInfoFuture = CompletableFuture.supplyAsync(CompletableFutureTest::getSkillInfo);
String userInfo = completableUserInfoFuture.get();
log.info("userInfo ==> 【{}】", userInfo);
String skillInfo = completableSkillInfoFuture.get();
log.info("skillInfo ==> 【{}】", skillInfo);
}
@SneakyThrows
@Test
public void testSupplyAsyncAndAllOf() {
StopWatch stopWatch = new StopWatch();
stopWatch.start("testSupplyAsyncAndAllOf");
CompletableFuture<String> completableUserInfoFuture = CompletableFuture.supplyAsync(CompletableFutureTest::getUserInfo, fixedExecutorService);
TimeUnit.SECONDS.sleep(2L);
CompletableFuture<String> completableSkillInfoFuture = CompletableFuture.supplyAsync(CompletableFutureTest::getSkillInfo);
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(completableUserInfoFuture, completableSkillInfoFuture);
List<CompletableFuture<String>> completableFutureList = new ArrayList<>();
completableFutureList.add(completableUserInfoFuture);
completableFutureList.add(completableSkillInfoFuture);
CompletableFuture<List<String>> completableFuture = voidCompletableFuture.thenApply(v -> {
log.info("allOf ==> 【{}】", v);
return completableFutureList.stream().map(CompletableFuture::join).collect(Collectors.toList());
});
stopWatch.stop();
stopWatch.start("get");
List<String> strings = completableFuture.get();
System.out.println("strings = " + strings);
stopWatch.stop();
log.info("【testSupplyAsyncAndAllOf】::stopWatch.prettyPrint ==> 【{}】", stopWatch.prettyPrint());
}
@SneakyThrows
@Test
public void testThenRun() {
CompletableFuture<String> firstFuture = CompletableFuture.supplyAsync(() -> "first");
TimeUnit.SECONDS.sleep(2L);
CompletableFuture<Void> thenRun = firstFuture.thenRun(() -> log.info("firstFuture thenRun"));
log.info("firstFuture.get() ==> 【{}】", firstFuture.get());
log.info("thenRun.get() ==> 【{}】", thenRun.get());
}
@SneakyThrows
@Test
public void testThenAccept() {
CompletableFuture<String> firstFuture = CompletableFuture.supplyAsync(() -> "first");
TimeUnit.SECONDS.sleep(2L);
CompletableFuture<Void> thenAccept = firstFuture.thenAccept((s) -> {
if (Objects.equals(s, "first")) {
log.info("firstFuture thenAccept");
} else {
log.error("firstFuture thenAccept else");
}
});
log.info("firstFuture.get() ==> 【{}】", firstFuture.get());
log.info("thenAccept.get() ==> 【{}】", thenAccept.get());
}
@SneakyThrows
@Test
public void testThenApply() {
CompletableFuture<String> firstFuture = CompletableFuture.supplyAsync(() -> "first");
TimeUnit.SECONDS.sleep(2L);
CompletableFuture<String> thenApply = firstFuture.thenApply((s) -> {
if (Objects.equals(s, "first")) {
return "thenApply success";
} else {
return "thenApply error";
}
});
log.info("firstFuture.get() ==> 【{}】", firstFuture.get());
log.info("thenApply.get() ==> 【{}】", thenApply.get());
}
@SneakyThrows
@Test
public void testExceptionally() {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException();
})
.exceptionally(ex -> "errorResultA")
.thenApply(resultA -> resultA + " resultB")
.thenApply(resultB -> resultB + " resultC")
.thenApply(resultC -> resultC + " resultD");
System.out.println(future.join());
}
@Test
public void handle() throws Exception {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {
@Override
public Integer get() {
return new Random().nextInt(10);
}
}).handle(new BiFunction<Integer, Throwable, Integer>() {
@Override
public Integer apply(Integer param, Throwable throwable) {
int result = -1;
if (throwable == null) {
result = param * 2;
} else {
System.out.println(throwable.getMessage());
}
return result;
}
});
System.out.println(future.get());
}
@SneakyThrows
@Test
public void testWhenComplete() {
CompletableFuture<String> firstFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread().getName() = " + Thread.currentThread().getName());
return "firstFuture";
});
TimeUnit.SECONDS.sleep(2L);
CompletableFuture<String> resFuture = firstFuture.whenComplete((a, throwable) -> {
System.out.println("Thread.currentThread().getName() = " + Thread.currentThread().getName());
System.out.println("上个任务执行完啦,还把" + a + "传过来");
});
log.info("resFuture.get() ==> 【{}】", resFuture.get());
}
@SneakyThrows
@Test
public void testAnyOf() {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "future1";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "future2";
});
CompletableFuture<Object> cfQuery = CompletableFuture.anyOf(future1, future2);
CompletableFuture<Double> resFuture = cfQuery.thenApplyAsync((s) -> {
return "future1".equals(s) ? 1.0 : 2.0;
});
log.info("future1.get() ==> 【{}】", future1.get());
log.info("future2.get() ==> 【{}】", future2.get());
log.info("resFuture.get() ==> 【{}】", resFuture.get());
}
@Test
public void runAfterEither() {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "future1";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "future2";
});
CompletableFuture<Void> voidCompletableFuture = future1.runAfterEither(future2, () -> {
log.info("有一个已经完成了。。。。。");
});
voidCompletableFuture.join();
}
@Test
public void thenCombine() throws Exception {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello future1";
}
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
return "hello future2";
}
});
CompletableFuture<String> result = future1.thenCombine(future2, new BiFunction<String, String, String>() {
@Override
public String apply(String t, String u) {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return t + " " + u;
}
});
System.out.println(result.get());
}
@Test
public void thenAcceptBoth() {
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
@Override
public Integer get() {
int t = 1;
try {
TimeUnit.SECONDS.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("f1=" + t);
return t;
}
});
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
@Override
public Integer get() {
int t = 2;
try {
TimeUnit.SECONDS.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("f2=" + t);
return t;
}
});
CompletableFuture<Void> voidCompletableFuture = f1.thenAcceptBoth(f2, new BiConsumer<Integer, Integer>() {
@Override
public void accept(Integer t, Integer u) {
System.out.println("f1=" + t + ";f2=" + u + ";");
}
});
try {
voidCompletableFuture.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
@Test
public void applyToEither() throws Exception {
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
@Override
public Integer get() {
int t = 2;
try {
TimeUnit.SECONDS.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("f1=" + t);
return t;
}
});
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
@Override
public Integer get() {
int t = 3;
try {
TimeUnit.SECONDS.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("f2=" + t);
return t;
}
});
CompletableFuture<Integer> result = f1.applyToEither(f2, new Function<Integer, Integer>() {
@Override
public Integer apply(Integer t) {
System.out.println(t);
return t * 2;
}
});
System.out.println(result.get());
}
@Test
public void acceptEither() throws Exception {
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
@Override
public Integer get() {
int t = 2;
try {
TimeUnit.SECONDS.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("f1=" + t);
return t;
}
});
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
@Override
public Integer get() {
int t = 3;
try {
TimeUnit.SECONDS.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("f2=" + t);
return t;
}
});
CompletableFuture<Void> result = f1.acceptEither(f2, new Consumer<Integer>() {
@Override
public void accept(Integer t) {
System.out.println(t);
}
});
log.info("【acceptEither】::result.get() ==> 【{}】", result.get());
}
}
package com.xiaobu.juc.CompletableFuture;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
@Slf4j
public class CompletableFutureDemo3 {
public static ExecutorService fixedExecutorService = Executors.newFixedThreadPool(5);
public static void main(String[] args) throws Exception {
try {
futureTest();
completableFutureTest();
log.info("【main】::主线程 ");
TimeUnit.SECONDS.sleep(5);
} finally {
fixedExecutorService.shutdown();
}
}
private static void completableFutureTest() {
log.info("【main】:: CompletableFuture start!");
CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "CompletableFuture finished";
}).whenComplete((r, t) -> {
log.info("【main】::r ==> [{}],t ==> [{}]", r, t);
});
}
private static void futureTest() throws InterruptedException, ExecutionException {
log.info("【main】::Future start!");
Future<?> future = fixedExecutorService.submit(() -> {
TimeUnit.SECONDS.sleep(1);
return "Future finished";
});
log.info("【main】::future.get() ==> [{}]", future.get());
}
}
参考:
CompletableFuture 使用详解