线程异步中CompletableFuture中方法处理方案实例

1.线程异步

多线程并发时,多个线程同时请求同一个资源,必然导致此资源的数据不安全,例如:A线程要请求某个资源,但是此资源正在被B线程使用中,因为没有同步机制存在,A线程仍然请求的到,A线程无需等待

1.1CompletableFuture

CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合 CompletableFuture 的方法

1.2 CompletableFuture的异步方法

1.2.1supplyAsync方法

线程执行后有返回值

1.2.1.1 supplyAsync代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> ucompletableFuture =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future开始......");
            int i=10/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i);
            System.out.println("子线程future结束......");
            return  i;
        });
        //调用异步编排future
        Integer integer=ucompletableFuture.get();
        System.out.println("异步编排的返回值为"+integer);
    }

}

/** 返回结果
 * 子线程future开始......
 * 线程名称ForkJoinPool.commonPool-worker-1线程的值为5
 * 子线程future结束......
 * 异步编排的返回值为5
 */

1.2.2runAsync方法

线程执行之后无返回值

1.2.2.1 runAsync 代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        //定义线程池子
        ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
                4,
                1,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                //既不抛出错误也继续执行
                new ThreadPoolExecutor.CallerRunsPolicy());
        CompletableFuture<Void> future=CompletableFuture.runAsync(()->{
            System.out.println("子线程future开始......");
            int i=10/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i);
            System.out.println("子线程future结束......");
        },threadPoolExecutor);
        future.get();
    }

}

/** 返回结果
 * 子线程future开始......
 * 线程名称pool-1-thread-1线程的值为5
 * 子线程future结束......
 */

1.2.3thenRunAsync方法

两个线程,1个线程执行之后在执行第2个线程

1.2.3.1 thenRunAsync代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        //定义线程池子
        ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
                4,
                1,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                //既不抛出错误也继续执行
                new ThreadPoolExecutor.CallerRunsPolicy());
        CompletableFuture<Void> completableFuture =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future开始......");
            int i=10/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i);
            System.out.println("子线程future结束......");
            return  i;
        },threadPoolExecutor).thenRunAsync(()->{

            System.out.println("子线程thenrun执行......");
            System.out.println("线程名称"+Thread.currentThread().getName());
            System.out.println("子线程thenrun结束......");
        },threadPoolExecutor);
        //调用执行
        completableFuture.get();
        System.out.println("主线程main结束......");
    }

}

/** 返回结果
 *主线程main开始......
 * 子线程future开始......
 * 线程名称pool-1-thread-1线程的值为5
 * 子线程future结束......
 * 子线程thenrun执行......
 * 线程名称pool-1-thread-2
 * 子线程thenrun结束......
 * 主线程main结束......
 */

1.2.4 supplyAsync方法

将上一个线程返回值返回给下一个线程

1.2.4.1 supplyAsync代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        CompletableFuture<Integer> completableFuture =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future开始......");
            int i=10/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i);
            System.out.println("子线程future结束......");
            return  i;
        }).thenApply((i)->{

            System.out.println("接受的返回值的结果为"+i);
            int k=i*5;
            System.out.println("相乘的结果为"+k);
            return  k;
        });
        //调用异步方法
        Integer I=completableFuture.get();
        System.out.println("返回的结果为"+I);
    }

}

/** 返回结果
 主线程main开始......
 子线程future开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为5
 子线程future结束......
 接受的返回值的结果为5
 相乘的结果为25
 返回的结果为25
 */

1.2.5 thenAccept方法

接受上一个线程返回值

1.2.5.1 thenAccept代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        CompletableFuture<Void> thenAccept =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future开始......");
            int i=10/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i);
            System.out.println("子线程future结束......");
            return i;
        }).thenAccept((i)->{
            System.out.println("接受的返回值的结果为"+i);
            int k=i*5;
            System.out.println("相乘的结果为"+k);
        });
        //调用异步方法
        thenAccept.get();
        System.out.println("主线程main结束......");
    }

}

/** 返回结果
 主线程main开始......
 子线程future开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为5
 子线程future结束......
 接受的返回值的结果为5
 相乘的结果为25
 主线程main结束......
 */
1.2.6 thenCompose方法

有返回值,返回值为U,两个CompletionStage流水线操作,将上一个线程的返回值返回给第二个线程,继续传递

1.2.6.1 thenCompose代码示例

package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        CompletableFuture<Integer> thenAccept =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future开始......");
            int i=10/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i);
            System.out.println("子线程future结束......");
            return i;
        }).thenCompose(new Function<Integer, CompletionStage<Integer>>() {
            @Override
            public CompletionStage<Integer> apply(Integer t) {
                CompletableFuture<Integer> future =CompletableFuture.supplyAsync(()->{
                    System.out.println("子线程thenAccept开始......");
                    int k=t/5;
                    System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+k);
                    System.out.println("子线程thenAccept结束......");
                    return k;
                });
                return future;
            }
        });
        //调用异步方法
        thenAccept.get();
        System.out.println("主线程main结束......");
    }

}

/** 返回结果
 主线程main开始......
 子线程future开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为5
 子线程future结束......
 子线程thenAccept开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为1
 子线程thenAccept结束......
 主线程main结束......
 */
 */

1.2.7 thenCombine方法

两个线程结束之后取两个线程的返回值

1.2.7.1 thenCombine代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        CompletableFuture<Integer> f1 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future1开始......");
            int i1=10/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i1);
            System.out.println("子线程future1结束......");
            return i1;
        });
        CompletableFuture<Integer> f2 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future2开始......");
            int i2=20/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i2);
            System.out.println("子线程future2结束......");
            return i2;
        });
        //t为第一个线程的返回值,u为第二个方法的返回值
        CompletableFuture<Integer> thenCombine = f1.thenCombine(f2, (t, u) -> {
            System.out.println("第一个线程的执行返回的结果"+t);
            System.out.println("第二个线程的执行返回的结果"+u);
            return  t+u;

        });
        //调用异步
        Integer integer=thenCombine.get();
        System.out.println("异步的调用方法为:"+integer);
        System.out.println("主线程main结束......");
    }

}

/** 返回结果
 主线程main开始......
 子线程future1开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为5
 子线程future1结束......
 子线程future2开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为10
 子线程future2结束......
 第一个线程的执行返回的结果5
 第二个线程的执行返回的结果10
 异步的调用方法为:15
 主线程main结束......
 */

1.2.8 thenAcceptBoth方法

等两个线程结束之后接收两个线程的返回值,不做处理,无返回值

1.2.8.1 thenAcceptBoth代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        CompletableFuture<Integer> f1 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future1开始......");
            int i1=10/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i1);
            System.out.println("子线程future1结束......");
            return i1;
        });
        CompletableFuture<Integer> f2 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future2开始......");
            int i2=20/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i2);
            System.out.println("子线程future2结束......");
            return i2;
        });
        //t为第一个线程的返回值,u为第二个方法的返回值
        CompletableFuture<Void> acceptBoth = f1.thenAcceptBoth(f2, (t, u) -> {
            System.out.println("第一个线程的执行返回的结果" + t);
            System.out.println("第二个线程的执行返回的结果" + u);
        });
        //调用异步
        acceptBoth.get();
        System.out.println("主线程main结束......");
    }

}

/** 返回结果
 主线程main开始......
 子线程future1开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为5
 子线程future1结束......
 子线程future2开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为10
 子线程future2结束......
 第一个线程的执行返回的结果5
 第二个线程的执行返回的结果10
 主线程main结束......
 */

1.2.9 runAfterBoth方法

设置两个线程的执行顺序,1个线程结束之后另外一个线程才能够执行

1.2.9.1 runAfterBoth代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        CompletableFuture<Integer> f1 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future1开始......");
            int i1=10/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i1);
            System.out.println("子线程future1结束......");
            return i1;
        });
        CompletableFuture<Integer> f2 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future2开始......");
            int i2=20/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i2);
            System.out.println("子线程future2结束......");
            return i2;
        });
        //t为第一个线程的返回值,u为第二个方法的返回值
        CompletableFuture<Void> runAfterBoth = f1.runAfterBoth(f2, () -> {
            System.out.println("有一个任务在执行.......runAfterBoth在执行");
        });
        //调用异步
        runAfterBoth.get();
        System.out.println("主线程main结束......");
    }

}

/** 返回结果
 主线程main开始......
 子线程future1开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为5
 子线程future1结束......
 子线程future2开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为10
 子线程future2结束......
 有一个任务在执行.......runAfterBoth在执行
 主线程main结束......
 */

1.2.10 runAfterBoth方法

返回两个线程的其中一个的返回值

1.2.10.1 runAfterBoth代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        CompletableFuture<Integer> f1 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future1开始......");
            int i1=10/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i1);
            System.out.println("子线程future1结束......");
            return i1;
        });
        CompletableFuture<Integer> f2 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future2开始......");
            int i2=20/2 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i2);
            System.out.println("子线程future2结束......");
            return i2;
        });
        //t为第一个线程的返回值,u为第二个方法的返回值 OR
        CompletableFuture<Integer> applyToEither = f1.applyToEither(f2,r -> {
            System.out.println("applyToEither线程名称,参数为"+r);
            return r;
        });
        //调用异步
        applyToEither.get();
        System.out.println("主线程main结束......");
    }

}

/** 返回结果
 主线程main开始......
 子线程future1开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为5
 子线程future1结束......
 子线程future2开始......
 线程名称ForkJoinPool.commonPool-worker-1线程的值为10
 子线程future2结束......
 applyToEither线程名称,参数为5
 主线程main结束......
 */

1.2.11 exceptionally方法

线程执行过程中异常抛出处理

1.2.11.1 exceptionally代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        CompletableFuture<Integer> f1 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future1开始......");
            int i1=10/0 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i1);
            System.out.println("子线程future1结束......");
            return i1;
        }).exceptionally((t)->{
            System.out.println("业务执行失败:"+t.getMessage());
            return null;
        });

        //调用异步
        f1.get();
        System.out.println("主线程main结束......");
    }

}

/** 返回结果
 主线程main开始......
 子线程future1开始......
 业务执行失败:java.lang.ArithmeticException: / by zero
 主线程main结束......
 */

1.2.12 whenComplete方法

whenComplete:对线程抛出的返回值和异常进行处理,返回值为 T,异常为 U,源码如下:

    public CompletableFuture<T> whenComplete(
            BiConsumer<? super T, ? super Throwable> action) {
        return uniWhenCompleteStage(null, action);
1.2.12.1 whenComplete代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        CompletableFuture<Integer> f1 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future1开始......");
            int i1=10/0 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i1);
            System.out.println("子线程future1结束......");
            return i1;
        }).whenComplete((t,u)->{
            System.out.println("执行结果为"+t);
            if (u!=null){
                System.out.println("业务执行失败:"+u.getMessage());
            }
        });

        //调用异步
        Integer integer=f1.get();
        System.out.println("最终执行结果为"+integer);
        System.out.println("主线程main结束......");
    }

}

/** 返回结果
 主线程main开始......
 子线程future1开始......
 执行结果为null
 业务执行失败:java.lang.ArithmeticException: / by zero
 */

1.1.13 handle方法

对线程抛出的返回值和异常进行处理,返回值为 T,异常为 U

1.1.13.1 handle代码示例
package com.kkb.ThreadBinfa;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class Test001 {
    public  static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程main开始......");
        CompletableFuture<Integer> f1 =CompletableFuture.supplyAsync(()->{
            System.out.println("子线程future1开始......");
            int i1=10/0 ;
            System.out.println("线程名称"+Thread.currentThread().getName()+"线程的值为"+i1);
            System.out.println("子线程future1结束......");
            return i1;
        }).handle((t,u)->{
            int res=-1;
            System.out.println("执行结果为"+t);
            if (u!=null){
                System.out.println("业务执行失败:"+u.getMessage());
            }else{
                res=t*5;
            }
            return res;
        });

        //调用异步
        Integer integer=f1.get();
        System.out.println("最终执行结果为"+integer);
        System.out.println("主线程main结束......");
    }

}

/** 返回结果
 主线程main开始......
 子线程future1开始......
 执行结果为null
 业务执行失败:java.lang.ArithmeticException: / by zero
 最终执行结果为-1
 主线程main结束......
 */

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

飞扬晴雪

学习的路上,感谢你的支持!

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

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

打赏作者

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

抵扣说明:

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

余额充值