【Java】CompletableFuture

CompletableFuture是java8中引入的机制,为了弥补异步执行时Future机制的不足。

那么光是用Future会有什么问题?

主要是无法做到回调机制以及多任务的协同。

CompletableFuture实现了CompletionStage接口,提供了多种任务协同的回调方法,使得异步回调写起来很方便。

其实future和completableFuture都是异步编程的模式,前者是需要主动获取结果的,后者是回调。

 

1 创建

    @Test
    public void testCreate() throws ExecutionException, InterruptedException {

        CompletableFuture<Void> c1 = CompletableFuture.runAsync(() -> {
            System.out.println("runAsync");
        });

        CompletableFuture<String> c2 = CompletableFuture.supplyAsync(() -> "supplyAsync");
        System.out.println(c2.get());

        ExecutorService service = Executors.newFixedThreadPool(10);
        CompletableFuture<Void> c3 = CompletableFuture.runAsync(() -> {
            System.out.println("runAsync");
        }, service);

        CompletableFuture<String> c4 = CompletableFuture.supplyAsync(() -> "supplyAsync", service);
        System.out.println(c4.get());
    }

提供了四种api,两个角度:是否有返回值;是否指定线程池(默认和指定)。

 

2 转换

    @Test
    public void testTransfer() {
        CompletableFuture.supplyAsync(() -> 1)
                .thenApply(i -> 1 + 1)
                .thenAccept(i -> {
                    System.out.println(i);
                });

        CompletableFuture.supplyAsync(() -> 1).thenRun(() -> {
            System.out.println("thenRun");
        });
    }

其实就是最基本的异步回调,主要有三种:

apply:转换;

accept:消耗;

run:无参消耗;

每一种都有同步和异步两种,异步又分为指定线程池和默认线程池。

后面所有的api都支持这种分类。

 

3 结合

@Test
    public void testCombine() throws ExecutionException, InterruptedException {
        int r = CompletableFuture.supplyAsync(() -> 1).thenCombine(CompletableFuture.supplyAsync(() -> 2), (i, j) -> i + j).get();
        Assert.assertTrue(r == 3);
    }

    @Test
    public void testMany() throws InterruptedException, ExecutionException {
        List<CompletableFuture<Integer>> jobs = Lists.newArrayList(
                CompletableFuture.supplyAsync(() -> {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return 1;
                }),
                CompletableFuture.supplyAsync(() -> {
                    return 2;
                })
        );
        CompletableFuture.allOf(
            jobs.toArray(new CompletableFuture[jobs.size()])
        ).thenRun(()->{
            int result = jobs.stream().map(c-> {
                try {
                    int tt = c.get();
                    System.out.println();
                    return tt;
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                    return -99;
                }
            }).reduce(0, (sum, i)->sum+i);
            System.out.println(result);
        });

        System.out.println("#########");
        int result2 = (int) CompletableFuture.anyOf(
                jobs.toArray(new CompletableFuture[jobs.size()])
        ).get();
        System.out.println(result2);
        Thread.sleep(10000);
    }

combine可以结合两个任务;

allOf执行完所有的任务才返回,后面需要遍历全部的job来自行获取结果;

anyOf执行完其中任意一个就返回。

 

异常

    @Test
    public void testException() throws ExecutionException, InterruptedException {
        CompletableFuture r = CompletableFuture.supplyAsync(()->{
            throw new RuntimeException();
        }).exceptionally(e->{
            System.out.println(e);
            return 1;
        });
    }

正常基于future的多线程,如果有异常,执行时不会报错,只会在主动get时报错。

completableFuture可以使用exceptionally里面对异常进行一次补救。

 

参考:https://segmentfault.com/a/1190000014479792

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值