如何使用CompletableFuture异步编程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

如何使用CompletableFuture异步编程


例子

串行执行

public class Test1 {
    public static void main(String[] args) {
        Long start = System.currentTimeMillis();
        task1();
        task2();
        Long end = System.currentTimeMillis();
        System.out.println("执行时长------>"+ (end - start) / 1000.0 +"秒");

    }
    private static void task1() {
        try {
            Thread.sleep(5000);
            System.out.println("任务1执行成功");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    private static void task2() {
        try {
            Thread.sleep(3000);
            System.out.println("任务2执行成功");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
-----------------------------------
任务1执行成功
任务2执行成功
执行时长------>8.014-----------------------------------

CompletableFuture异步

public class Test1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Long start = System.currentTimeMillis();
        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(5);

        // 执行任务1 // supplyAsync  带返回值
        CompletableFuture<String> comFeature1 = CompletableFuture.supplyAsync(()->{
            task1();
            return "task1Success";
        }, executor);

        // 执行任务2  // supplyAsync  带返回值
        CompletableFuture<String> comFeature2 = CompletableFuture.supplyAsync(()->{
            task2();
            return "task2Success";
        });

        // 等待任务1和任务2执行完毕后,获取返回值 再执行后续操作
        String join1 = comFeature1.get();
        String join2 = comFeature2.get();
        // runAsync  不带返回值
        CompletableFuture<Void> feature3 = CompletableFuture.runAsync(() -> {
            System.out.println("任务1返回----->"+join1);
            System.out.println("任务2返回----->"+join2);
        });
        // 等待操作执行完成
        feature3.get();
        // 关闭线程池
        executor.shutdown();
        Long end = System.currentTimeMillis();
        System.out.println("执行时长------>"+ (end - start) / 1000.0 +"秒");

    }
    private static void task1() {
        try {
            Thread.sleep(5000);
            System.out.println("任务1执行成功");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    private static void task2() {
        try {
            Thread.sleep(3000);
            System.out.println("任务2执行成功");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
---------------------------------
任务2执行成功
任务1执行成功
任务1返回----->task1Success
任务2返回----->task2Success
执行时长------>5.048---------------------------------

supplyAsync回调

回调函数方法,thenAppply(Function<T,R>)方法,该方法可以将任务执行完成之后,自动将结果获取,并对结果进行操作。转换后的结果可以交给主线程获取,也可以进一步转换。也就是说这个结果thenApply(Function<T,R>)是一个带返回值的回调方法

public class Test1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Long start = System.currentTimeMillis();

        // 执行任务1
        CompletableFuture<String> comFeature1 = CompletableFuture.supplyAsync(()->{
            task1();
            return "task1Success";
        });

        // 执行任务2
        CompletableFuture<String> comFeature2 = CompletableFuture.supplyAsync(()->{
            task2();
            return "task2Success";
        }).thenApply(result->{
         	//等待任务1执行完成拿到返回值
            String task1Str = comFeature1.join();
            return result+"--"+task1Str;
        });

        // 等待操作执行完成
        String result = comFeature2.join();
        System.out.println("执行结果:-------------->"+result);
        Long end = System.currentTimeMillis();
        System.out.println("执行时长------>"+ (end - start) / 1000.0 +"秒");

    }
    private static void task1() {
        try {
            System.out.println("任务1执行开始");
            Thread.sleep(5000);
            System.out.println("任务1执行结束");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    private static void task2() {
        try {
            System.out.println("任务2执行开始");
            Thread.sleep(3000);
            System.out.println("任务2执行结束");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
---------------------------
任务1执行开始
任务2执行开始
任务2执行结束
任务1执行结束
执行结果:-------------->task2Success--task1Success
执行时长------>5.041

thenRun无回调

如果我们不对异步执行结果进行加工处理,只是想知道该异步方法是否执行完成,则可以使用thenRun(Function<T,R>) 方法。这个方法只是一个异步完成的通知方法,告诉开发者,异步方法执行完成了。

public class Test1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Long start = System.currentTimeMillis();

        // 执行任务1
        CompletableFuture<String> comFeature1 = CompletableFuture.supplyAsync(()->{
            task1();
            return "task1Success";
        });

        // 执行任务2
        CompletableFuture.supplyAsync(()->{
            task2();
            return "task2Success";
        }).thenRun(()->{
            System.out.println("task2222回调了--------->");
        }).join();

        Long end = System.currentTimeMillis();
        System.out.println("执行时长------>"+ (end - start) / 1000.0 +"秒");

    }
    private static void task1() {
        try {
            System.out.println("任务1执行开始");
            Thread.sleep(5000);
            System.out.println("任务1执行结束");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    private static void task2() {
        try {
            System.out.println("任务2执行开始");
            Thread.sleep(3000);
            System.out.println("任务2执行结束");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
--------------------
任务1执行开始
任务2执行开始
任务2执行结束
task2222回调了--------->
执行时长------>3.047

两个任务的组合

/*
 * 进行两个异步任务的编排调用-------这两个异步任务可存在依赖关系
 * 例如 任务1 执行完成的结果 正是任务2的条件
 * */
public class Test1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Long start = System.currentTimeMillis();

        // 执行任务1
        CompletableFuture<String> comFeature1 = CompletableFuture.supplyAsync(() -> {
            task1();
            return "task1Success";
        });

        // 将任务1结果传给任务2
        CompletableFuture<String> stringCompletableFuture = comFeature1.thenCompose(result -> CompletableFuture.supplyAsync(()->{
            String str = result+"---"+"task1Success";
            return str.trim();
        }));
        String join = stringCompletableFuture.join();
        System.out.println("执行结果为:----------->" + join);
        Long end = System.currentTimeMillis();
        System.out.println("执行时长------>" + (end - start) / 1000.0 + "秒");

    }

    private static void task1() {
        try {
            System.out.println("任务1执行开始");
            Thread.sleep(5000);
            System.out.println("任务1执行结束");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
------------------------------
任务1执行开始
任务1执行结束
执行结果为:----------->task1Success---task1Success
执行时长------>5.034

总结

如果需要回调方法对结果进行处理,并且需要回调方法处理完成之后,返回具体处理结果。则使用thenApply(Function<T,R>)方法。

如果需要回调方法对结果进行处理,回调方法处理完成之后,不返回具体处理结果。则使用thenAeecpt(Function<T,R>) 方法。

如果不对结果进行处理,只是通知开发完成异步方法的调用了,则使用thenRun(Function<T,R>) 方法。

需要注意的是,这三个方法都支持 lamda 表达式和链式调用。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上海下小雨y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值