CompletableFuture异步编程

在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();
                }

            });

        });


    }
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页