在CompletableFuture中提供了四个静态方法用于创建异步任务
runAsync(Runnable runnable)
runAsync(Runnable runnable,Executor executor)
supplyAsync(Supplier<U> supplier)
supplyAsync(Supplier<U> supplier,Executor executor)
在该方法内部会创建异步任务,并把任务放入线程池中。并且runAsync()是没有返回值的。
根据源码可知,当传入Executor会使用指定线程池执行,如果没有传入则使用默认ForkJoinPool.commonPool()执
行,值得注意的是,commonPool中都是守护线程,主线程执行完,子线程也就over了。因此建议当任务非常耗
时,使用自定义线程池。
而supplyAsync()是有返回值的,
异步计算结果触发回调
当异步任务结束或者抛出异常时,还要根据结果来完成特定的操作,对于这种需求CompletableFuture也提供了方法进行实现
public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action,
Executor executor)
public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn)
其中只要尾缀是Async()的,都是重新开一个线程做操作的。示例如下:
使用whenComplete():
public class Demo1 {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(100);
System.out.println(Thread.currentThread().getName());
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() ‐> {
try {
System.out.println("异步任务线程:"+Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(3);
System.out.println("child run");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 123;
},executor);
System.out.println("main end");
try {
future.whenComplete(new BiConsumer<Integer, Throwable>() {
@Override
public void accept(Integer integer, Throwable throwable) {
System.out.println("结果触发任务线程:"+Thread.currentThread().getName());
System.out.println("特定任务执行");
}
});
}catch (Exception e){
e.printStackTrace();
}
executor.shutdown();
}
}
main
main end
异步任务线程:pool‐1‐thread‐1
child run
结果触发任务线程:pool‐1‐thread‐1
特定任务执行
使用.whenCompleteAsync():
public class Demo1 {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(100);
System.out.println(Thread.currentThread().getName());
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() ‐> {
try {
System.out.println("异步任务线程:"+Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(3);
System.out.println("child run");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 123;
},executor);
System.out.println("main end");
try {
future.whenCompleteAsync(new BiConsumer<Integer, Throwable>() {
@Override
public void accept(Integer integer, Throwable throwable) {
System.out.println("结果触发任务线程:"+Thread.currentThread().getName());
System.out.println("特定任务执行");
executor.shutdown();
}
},executor);
}catch (Exception e){
e.printStackTrace();
}
}
}
main
main end
异步任务线程:pool‐1‐thread‐1
child run
结果触发任务线程:pool‐1‐thread‐2
特定任务执行
使用exceptionally():
public class Demo1 {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(100);
System.out.println(Thread.currentThread().getName());
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() ‐> {
try {
System.out.println("异步任务线程:"+Thread.currentThread().getName());
int i=1/0;
TimeUnit.SECONDS.sleep(3);
System.out.println("child run");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 123;
},executor);
System.out.println("main end");
future.exceptionally(new Function<Throwable, Integer>() {
@Override
public Integer apply(Throwable throwable) {
System.out.println("异常结果触发任务线程:"+Thread.currentThread().getName());
System.out.println("异步任务执行失败:"+throwable.getMessage());
return null;
}
});
}
}
使用thenApply():
public class ThenApplyDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(100);
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() ‐> {
int value = 90;
System.out.println(value);
return value;
}, executor).thenApply(value‐>{
int result = value*10;
System.out.println(result);
return result;
});
try {
Integer result = future.get();
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
future.cancel(true);
} catch (ExecutionException e) {
e.printStackTrace();
future.cancel(true);
}finally {
executor.shutdown();
}
}
}
main
90
900
900
根据运行结果可以看到,此处通过thenApply()串接了两个任务,第二个方法会在第一个方法执行完成后触发,且第二个方法的执行依赖于第一个方法的执行结果。
thenCombine()使用:
在进行多异步任务执行时,有时不光要让任务之间串联执行,有时还要将多个任务执行结果进行合并处理,当两个异步任务都执行完毕后,它可以将两个任务进行合并,获取到两个任务的执行结果,进行合并处理,最后会
有返回值。
public class test {
public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(100);
System.out.println(Thread.currentThread().getName());
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("future1:"+Thread.currentThread().getName());
return "hello";
}, executorService);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("future2:"+Thread.currentThread().getName());
return "hei,hei";
}, executorService);
CompletableFuture<String> stringCompletableFuture = future1.thenCombineAsync(future2, (x1, x2) -> {
System.out.println("result:" + Thread.currentThread().getName());
return x1 + " " + x2;
}, executorService);
String s = stringCompletableFuture.get();
System.out.println(s);
System.out.println(stringCompletableFuture);
}
}
main
future1:pool-1-thread-1
future2:pool-1-thread-2
result:pool-1-thread-3
hello hei,hei
java.util.concurrent.CompletableFuture@3eb07fd3[Completed normally]
**thenAcceptBoth()使用与thenCombine()类似,当两个任务执行完,获取两个任务的结果进行特定处理,但thenAcceptBoth()**没有返回值
**applyToEither()**使用:当两个任务异步任务执行,谁先执行完,就以谁的结果为准,完成后续的业务处理,并且会进行结果值返回。
allOf()使用:
刚才的操作异步任务的数量,只能局限在两个,现在如果需要有任意多个异步任务进行组合操作的话,CompletableFuture中也提供了对应方法进行实现
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
public class test {
public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(100);
System.out.println(Thread.currentThread().getName());
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
int f1 = new Random().nextInt(100);
System.out.println("f1 value:" + f1);
return f1;
}, executorService);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
int f2 = new Random().nextInt(100);
System.out.println("f2 value:" + f2);
return f2;
}, executorService);
CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(()->{
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
int f3 = new Random().nextInt(100);
System.out.println("f3 value:" + f3);
return f3;
});
List<CompletableFuture<Integer>> list = new ArrayList<>();
list.add(future1);
list.add(future2);
list.add(future3);
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(list.toArray(new CompletableFuture[]{}));
voidCompletableFuture.thenRunAsync(()->{
AtomicReference<Integer> objectAtomicReference = new AtomicReference<>(0);
list.parallelStream().forEach((x)->{
Integer integer = null;
try {
integer = x.get();
Integer finalInteger = integer;
objectAtomicReference.updateAndGet(j->j+ finalInteger);
System.out.println(objectAtomicReference);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
});
}
}