一、是什么
是Java 8 新增加的Api,该类实现,Future和CompletionStage两个接口,提供了非常强大的Future的扩展功能,可以通过回调的方式处理计算结果
二、怎么用
1、创建异步任务:
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(10);
String SUCCESS = "success";
/**
*public static CompletableFuture<Void> runAsync(Runnable runnable)
* 没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码
*/
CompletableFuture<Void> runAsyncFuture = CompletableFuture.runAsync(() -> {
System.out.println("start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finish");
});
System.out.println("runAsync方式,未指定线程池------》"+ runAsyncFuture.get());
System.out.println();
/**
* public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
* 指定线程池,则使用指定的线程池运行
*/
CompletableFuture<Void> runAsyncFutureWithExecutor = CompletableFuture.runAsync(() -> {
System.out.println("start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finish");
}, executor);
System.out.println("runAsync方式,指定了线程池------》"+runAsyncFutureWithExecutor.get());
System.out.println();
/**
* public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
* 没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码
*/
CompletableFuture<String> supplyAsyncFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finish");
return SUCCESS;
});
System.out.println("supplyAsync方式,未指定线程池------》"+supplyAsyncFuture.get());
System.out.println();
/**
* public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
* 指定线程池,则使用指定的线程池运行
*/
CompletableFuture<String> supplyAsyncFutureWithExecutor = CompletableFuture.supplyAsync(() -> {
System.out.println("start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finish");
return SUCCESS;
}, executor);
System.out.println("supplyAsync方式,指定了线程池------》"+supplyAsyncFutureWithExecutor.get());
executor.shutdown();
}
2、异步回调
thenApply:
/**
* 第二个任务依赖第一个任务的结果,有入参,有返回值。
* public CompletableFuture thenApply(Function<? super T,? extends U> fn)
*/
CompletableFuture<Long> future = CompletableFuture.supplyAsync(()-> {
long result = new Random().nextInt(100);
System.out.println("result1=" + result);
return result;
}).thenApply(t-> {
long result = t * 5;
System.out.println("result2=" + result);
return result;
});
long result = future.get();
System.out.println(result);
thenAccept:
/**
* 该方法只是消费执行完成的任务,并可以根据上面的任务返回的结果进行处理。并没有后续的返回操作
* public CompletableFuture thenAccept(Consumer<? super T> action)
*/
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() ->{
int num= new Random().nextInt(10);
return num;
}).thenAccept(integer -> {
System.out.println(integer);
});
future.get();
thenRun:
/**
* 上个任务处理完成后,并不会把计算的结果传给 thenRun 方法。只是处理玩任务后,执行 thenAccept 的后续操作
* public CompletionStage thenRun(Runnable action)
* 入参是一个Runnable的实例,表示当得到上一步的结果时的操作
*/
CompletableFuture<Void> future = CompletableFuture.supplyAsync(()-> {
int num= new Random().nextInt(10);
return num;
}).thenRun(() -> {
System.out.println("thenRun ...");
});
future.get();
3、组合处理
runAfterBoth:
/**
* 两个CompletionStage,都完成了计算才会执行下一步的操作
* public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,
* Runnable action)
*/
CompletableFuture
.supplyAsync(() -> {
System.out.println(10);
return 10;
})
.runAfterBoth(CompletableFuture.supplyAsync(() -> {
System.out.println(20);
return 20;
}), () -> System.out.println("开始运行run"));
thenAcceptBoth:
/**
* 当两个CompletionStage都执行完成后,把结果一块交给thenAcceptBoth来进行消耗。
* public CompletableFuture thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T,? super U> action)
*/
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() ->{
String s="hujunxian";
return s;
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() ->{
String s1="2021";
return s1;
});
future2.thenAcceptBoth(future1, (s1,s) ->{
System.out.println(s1 + " , " + s);
});
thenCombine:
/**
* thenCombine 会把 两个 CompletionStage 的任务都执行完成后,把两个任务的结果一块交给 thenCombine 来处理。
* public <U,V> CompletableFuture thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
*/
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() ->{
String s="hello";
return s;
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(()-> {
String ss="hello";
return ss;
});
CompletableFuture<String> result = future1.thenCombine(future2, (t,u) ->{
String res=t+" , "+u;
return res;
});
System.out.println(result.get());
runAfterEither:
/**
* public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,
* 方法没有入参也没有返回值 Runnable action)
*/
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("s1");
return "s1";
}).runAfterEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("s2");
return "s2";
}), () -> System.out.println("hello world")).get();
acceptEither:
/**
* public CompletableFuture<Void> acceptEither(
* CompletionStage<? extends T> other, Consumer<? super T> action)
* 方法有入参无返回值
*/
Random random = new Random();
CompletableFuture
.supplyAsync(() -> {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
return "A";
})
.acceptEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
return "B";
}), System.out::println)
.get();
applyToEither:
/**
* 两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的转化操作,方法有入参有返回值
* public <U> CompletableFuture<U> applyToEither(
* CompletionStage<? extends T> other, Function<? super T, U> fn)
*/
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);
allOf/anyOf:
allOf是多个任务都执行完成后才会执行后面的操作;anyOf是多个任务只要其中一个执行完成就会执行后面的操作
/**
* public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
*/
Random random = new Random();
CompletableFuture.anyOf(
// CompletableFuture.allOf(
CompletableFuture.runAsync(() -> {
int a=random.nextInt(5000);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(a);
}),
CompletableFuture.runAsync(() -> {
int b=random.nextInt(5000);
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(b);
})).thenRun(()-> System.out.println("allOf")).get();
}