CompletableFuture 并发异步编程

在学习过程中碰到了这么个1.8的新特性,在此记录一下:

为了提高代码的执行效率,部分代码可以利用并发异步编程,达到优化的效果。

下面的可以说所有的方法都使用了线程池的方法进行测试,也可以使用直接利用lambda表达式直接写任务代码。都阔以。并且每个部分的具体解释,都在代码中有提现。

一、CompletableFuture有两个比较常用的方法:

package com.brave;

import java.util.concurrent.*;

public class CompletableFuture01 {


    public static void main(String[] args) {

        //创建一个线程池,用来执行线程任务
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                10,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        //利用completableFuture进行并发异步编程
        /**
         * runAsync 这个方法,没有返回值 ,那么CompletableFuture的泛型中就只能写Void
         */
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(()->{
            System.out.println("任务1 : " + Thread.currentThread().getName());
        },executor);

        /**
         * supplyAsync 这个方法,有返回值 ,那么CompletableFuture的泛型中可以写任意可返回的对象类型
         * 这里用Object代替所有的类型
         */
        CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(()->{
            System.out.println("任务1 : " + Thread.currentThread().getName());
            return 100;
        },executor);


    }
}

 二、如果线程执行完成需要对返回结果以及可能会发生的异常做处理,可以用whenCompleteAsync和exceptionally进行处理

package com.brave;

import java.util.concurrent.*;

public class CompletableFuture02 {


    public static void main(String[] args) {

        //创建一个线程池,用来执行线程任务
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                10,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        //利用completableFuture进行并发异步编程
        /**
         *    whenCompleteAsync可以接收前面线程的返回值以及异常,可以进行返回值的逻辑
         *    但是不能处理异常,并且没有返回值
         *    exceptionally  可以接收异常并处理异常,有返回值,返回值类型与前面线程的返回值类型相同
         */
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(()->{
            System.out.println("任务1 : " + Thread.currentThread().getName());
        },executor).whenCompleteAsync((result,exception)->{
            System.out.println("whenCompleteAsync1接收返回值和异常信息");
            System.out.println("result = " + result);
            System.out.println("exception = " + exception);
        },executor).exceptionally((exception) -> {
            System.out.println("exceptionally1处理异常");
            System.out.println(exception);
            return null;
        });

        /**
         *    whenCompleteAsync可以接收前面线程的返回值以及异常,可以进行返回值的逻辑
         *    但是不能处理异常,并且没有返回值
         *    exceptionally  可以接收异常并处理异常,有返回值,
         *    返回值类型与前面线程的返回值类型相同,前线程没有返回值,那么就返回null
         */
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(()->{
            System.out.println("任务2 : " + Thread.currentThread().getName());
            return 100;
        },executor).whenCompleteAsync((result,exception)->{
            System.out.println("whenCompleteAsync1接收返回值和异常信息");
            System.out.println("result = " + result);
            System.out.println("exception = " + exception);
        },executor).exceptionally((exception) -> {
            System.out.println("exceptionally2处理异常");
            System.out.println(exception);
            return 100;
        });


    }
}

三、针对对返回结果以及可能会发生的异常做处理,除了用上面两个方法,还可以用handleAsync来代替上面两个方法:

package com.brave;

import java.util.concurrent.*;

public class CompletableFuture03 {


    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //创建一个线程池,用来执行线程任务
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                10,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        System.out.println("========主线程开始=========" + Thread.currentThread().getName());

        //利用completableFuture进行并发异步编程
        /**
         *    handleAsync 可以说是替代了whenCompleteAsync和exceptionally
         *    相当于他们两个结合起来
         *    可以处理异常并拥有返回值
         */
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(()->{
            System.out.println("任务1 : " + Thread.currentThread().getName());
        },executor).handleAsync((result,exception)->{
            System.out.println("result = " + result);
            System.out.println("exception = " + exception);
            return null;
        },executor);



        /**
         *    handleAsync 可以说是替代了whenCompleteAsync和exceptionally
         *    相当于他们两个结合起来
         *    可以处理异常并拥有返回值
         */
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(()->{
            System.out.println("任务2 : " + Thread.currentThread().getName());
            return 100;
        },executor).handleAsync((result,exception)->{
            System.out.println("result = " + result);
            System.out.println("exception = " + exception);
            return result + 10;
        },executor);

        System.out.println("future2.get() = " + future2.get());

        System.out.println("=======主线程结束=========" + Thread.currentThread().getName());

    }
}

四、如果想要多个线程按照顺序执行,那么就使用thenRunAsync,thenAcceptAsync, thenApplyAsync这三个方法:

package com.brave;

import java.util.concurrent.*;

public class CompletableFuture04 {


    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //创建一个线程池,用来执行线程任务
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                10,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        System.out.println("========主线程开始=========" + Thread.currentThread().getName());
        //利用completableFuture进行并发异步编程
        //线程串行编程   最终的接收泛型要看最终的那个方法有没有返回值
        /**
         *    thenRunAsync 在前面线程完成之后执行的线程,没有返回值,没有参数
         *    可以让线程按顺序执行,因为不能接收前线程的返回值,所以在runAsync后面使用
         */
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(()->{
            System.out.println("任务1 : " + Thread.currentThread().getName());
        },executor).thenRunAsync(()->{
            System.out.println("任务1-1 : " + Thread.currentThread().getName());
        },executor);

        /**
         *    thenAcceptAsync 可以接收前面线程的返回值,但是本身没有返回值
         *     可以让线程按顺序执行 因为能接收前线程的返回值,所以在supplyAsync后面使用
         */
        CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(()->{
            System.out.println("任务2 : " + Thread.currentThread().getName());
            return 100;
        },executor).thenAcceptAsync((result)->{
            System.out.println("result = " + result);
        },executor);


        /**
         *    thenApplyAsync 可以接收前面线程的返回值,并且本身有返回值
         *    可以让线程按顺序执行 因为能接收前线程的返回值,所以在supplyAsync后面使用
         */
        CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务3 : " + Thread.currentThread().getName());
            return 100;
        }, executor).thenApplyAsync((result) -> {
            System.out.println("result = " + result);
            return result + 100;
        }, executor);

        System.out.println("=======主线程结束=========" + Thread.currentThread().getName());

    }
}

五、线程编排,如果想要在两个任务完成之后才能进行第三个任务,那么就是用runAfterBothAsync,thenAcceptBothAsync,thenCombinAsync这三个方法: 

package com.brave;

import java.util.concurrent.*;

public class CompletableFuture05 {


    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //创建一个线程池,用来执行线程任务
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                10,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        System.out.println("========主线程开始=========" + Thread.currentThread().getName());
        //利用completableFuture进行并发异步编程
        //线程编排运行  两个任务都完成之后才进行第三个任务


        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(()->{
            System.out.println("任务1 : " + Thread.currentThread().getName());
            return 20;
        },executor);


        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(()->{
            System.out.println("任务2 : " + Thread.currentThread().getName());
            return 100;
        },executor);

        /**
         * 不能接收前两个线程的返回值,本身也没有返回值
         */
        future1.runAfterBothAsync(future2,()->{
            System.out.println("任务3 : " + Thread.currentThread().getName());
        },executor);

        /**
         * 可以接收前两个线程的返回值,本身也没有返回值
         */
        future1.thenAcceptBothAsync(future2,(f1,f2)->{
            System.out.println("任务4 : " + Thread.currentThread().getName());
        },executor);


        /**
         * 可以接收前两个线程的返回值,本身有返回值
         */
        future1.thenCombineAsync(future2,(f1,f2)->{
            System.out.println("任务4 : " + Thread.currentThread().getName());
            return  f1 + f2;
        },executor);

        System.out.println("=======主线程结束=========" + Thread.currentThread().getName());

    }
}

六、线程编排,如果想要两个任务中,只要完成其中一个,就开始第三个任务,那么就用runAfterEitherAsync,acceptEitherAsync,applyToEitherAsync这三个方法:

package com.brave;

import java.util.concurrent.*;

public class CompletableFuture06 {


    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //创建一个线程池,用来执行线程任务
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                10,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        System.out.println("========主线程开始=========" + Thread.currentThread().getName());
        //利用completableFuture进行并发异步编程
        //线程编排运行  两个线程任意完成一个就执行第三个线程


        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(()->{
            System.out.println("任务1 : " + Thread.currentThread().getName());
            return 20;
        },executor);


        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(()->{
            System.out.println("任务2 : " + Thread.currentThread().getName());
            return 100;
        },executor);

        /**
         * 不能接收前两个线程中完成的那个线程的返回值,本身也没有返回值
         */
        future1.runAfterEitherAsync(future2,()->{
            System.out.println("任务3 : " + Thread.currentThread().getName());
        },executor);

        /**
         * 可以接收前两个线程中执行完成的那一个线程的返回值,本身没有返回值
         */
        future1.acceptEitherAsync(future2,(result)->{
            System.out.println("任务3 : " + Thread.currentThread().getName());
        },executor);

        /**
         * 可以接收前两个线程中执行完成的那一个线程的返回值,本身有返回值
         */
        future1.applyToEitherAsync(future2,(result)->{
            System.out.println("任务4 : " + Thread.currentThread().getName());
            return  result + 100;
        },executor);



        System.out.println("=======主线程结束=========" + Thread.currentThread().getName());

    }
}

七、多任务处理 ,多个任务想要一起运行就用allof,多任务运行只要其中一个任务执行完毕就进入主线程继续执行,剩下的线程仍然继续执行,那么就用anyof:

package com.brave;

import java.util.concurrent.*;

public class CompletableFuture07 {


    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //创建一个线程池,用来执行线程任务
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                10,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        System.out.println("========主线程开始=========" + Thread.currentThread().getName());
        //利用completableFuture进行并发异步编程
        //多任务处理  多个线程同时执行


        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(()->{
            System.out.println("任务1 : " + Thread.currentThread().getName());
            return 20;
        },executor);


        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(()->{
            System.out.println("任务2 : " + Thread.currentThread().getName());
            return 100;
        },executor);

        /**
         * 同时完成几个线程任务
         */
        CompletableFuture<Void> f = CompletableFuture.allOf(future1, future2);
        //阻塞方法:目的是等待所有线程执行完毕之后再回到主线程,
        // 不然就会出现,线程开始了,不管有没有执行完,就回到了主线程
        //f.get()   和  f.join()  都可以达到这个目的
        f.get();
//        f.join();
        //future1.get() 这个方法可以获得任务的返回值
        System.out.println("全部线程同时执行的" + future1.get() + "==" + future2.get());

        /**
         * anyof  是多任务中的任意一个完成之后,直接获取返回结果就可以
         */
        CompletableFuture<Object> future = CompletableFuture.anyOf(future1, future2);
        System.out.println("多任务任意执行完成一个就可以进行返回:" + future.get());


        System.out.println("=======主线程结束=========" + Thread.currentThread().getName());

    }
}

这就是CompletableFuture!!!ending!  

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值