扩展------CompletableFuture异步编排结合线程池技术

CompletableFuture也是java1.8新特性之一,是JUC包下的工具类,主要用于异步编排获取结果

 

异步执行任务

supplyAsync() :异步开启一个任务,并且指定线程池,可以有返回数据

runAsync():异步开启一个任务,并且指定线程池,但是不允许有返回数据

public static void main(String[] args) throws ExecutionException, InterruptedException {
    //创建一个线程池
    ExecutorService pool = Executors.newFixedThreadPool(10);


    //使用supplyAsync()执行一个任务,可以有返回值
    CompletableFuture<String> task = CompletableFuture.supplyAsync(()->{
        System.out.println("我开始执行任务了......."+Thread.currentThread().getName());
        return "good";
    },pool);
    //可以拿到异步任务的执行结果
    System.out.println(task.get());


    //使用runAsync()执行一个任务,不能有返回值
    CompletableFuture<Void> task1 = CompletableFuture.runAsync(()->{
        System.out.println("我开始执行任务了......."+Thread.currentThread().getName());
    },pool);
    pool.shutdownNow();
}

 

 任务编排

当我们有顺序执行任务的需求的时候,即这个任务需要上一个任务的结果等情况,需要进行编排

①thenApply(),thenAccept(),thenRun()

thenApply():有入参,有返回值,可获得前一个任务的返回值进行操作,并且可以返回数据

thenAccept():有入参,无返回值,可获得前一个任务的返回值进行操作,但是没有返回数据

thenRun():无入参,无返回值,不可获得前一个任务的返回值,也没有返回数据

ExecutorService pool = Executors.newFixedThreadPool(5);
//thenApply(),有入参,有返回值
CompletableFuture<String> task = CompletableFuture.supplyAsync(()->{
    System.out.println("task任务一先执行"+Thread.currentThread().getName());
    return "1";
},pool).thenApply(s -> {
    System.out.println("前面任务的返回值:"+s);
    System.out.println("task任务二后执行"+Thread.currentThread().getName());
    return "2";
});
System.out.println(task.get());


//thenAccept(),有入参,无返回值
CompletableFuture<Void> task1 = CompletableFuture.supplyAsync(()->{
    System.out.println("task1任务一先执行"+Thread.currentThread().getName());
    return "1";
},pool).thenAccept(s -> {
    System.out.println("前面任务的返回值:"+s);
    System.out.println("task1任务二后执行"+Thread.currentThread().getName());
});


//thenRun(),无入参,无返回值
CompletableFuture<Void> task2 = CompletableFuture.supplyAsync(()->{
    System.out.println("task2任务一先执行"+Thread.currentThread().getName());
    return "1";
},pool).thenRun(() -> System.out.println("task2任务二后执行"+Thread.currentThread().getName()));

pool.shutdownNow();

 

②thenCombine()

thenCombine():有两个入参,再将并行任务1,2的结果进行统一处理计算

ExecutorService pool = Executors.newFixedThreadPool(4);
//任务1
CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+"我先去1号目的地需要花费"+300+"块");
    return 300;
},pool);
//任务2
CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+"我再去2号目的地需要花费"+500+"块");
    return 500;
},pool);

CompletableFuture<Integer> result = task1.thenCombine(task2, (r1, r2) -> {
    System.out.println(Thread.currentThread().getName()+"最近计算出总费用"+(r1+r2));
    return r1+r2;
});

 

③runAfterEither(),runAfterBoth()

runAfterEither():两个任务,但凡有一个任务执行完了,就会执行后续的代码

runAfterBoth():两个任务,两个任务都执行完了才会执行后续代码

ExecutorService pool = Executors.newFixedThreadPool(4);

CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+"我先去1号目的地需要花费"+300+"块");
    return 300;
},pool);

CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+"我再去2号目的地需要花费"+500+"块");
    return 500;
},pool);

//有任何一个执行完就会执行后续代码
task1.runAfterEither(task2,()->{ System.out.println("!!!!!!!"); });
//两个都执行完才会执行后续代码
task1.runAfterBoth(task2,()->{ System.out.println("+++++++"); });

pool.shutdownNow();

④allOf(),anyOf()

allOf():

anyOf():

ExecutorService pool = Executors.newFixedThreadPool(4);

CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+"我先去1号目的地需要花费"+300+"块");
    return 300;
},pool);

CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+"我再去2号目的地需要花费"+500+"块");
    for (int i = 0; i < 1000; i++) {
        int x=0;
        x+=i;
    }
    return 500;
},pool);

CompletableFuture<Integer> result = task1.thenCombine(task2, (r1, r2) -> {
      System.out.println(Thread.currentThread().getName()+"最近计算出总费用"+(r1+r2));
      return r1+r2;
  });

//只有这两个任务全执行完才会往下执行主线程
CompletableFuture.allOf(task1,task2).join();
System.out.println("我是主线程");

pool.shutdownNow();

获取结果

get():阻塞等待结果

getNow():like获得现在的结果

停止任务

 complete():直接让任务完成

 cacel():如果任务还没开始/正在执行,则可以取消任务,设置取消标记为true。如果任务已经完成了,则设置取消标志为false

 实战事例

public static void main(String[] args) throws ExecutionException, InterruptedException {
    //获取服务器的核心数
    int cores = Runtime.getRuntime().availableProcessors();
    //自定义创建线程池
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
            cores+1,        //核心线程数
            cores+1,    //最大线程数
            0,            //空闲线程存活时间
            TimeUnit.SECONDS,           //时间单位
            new ArrayBlockingQueue<>(10),   //任务等待队列
            Executors.defaultThreadFactory(),       //线程工厂
            new ThreadPoolExecutor.AbortPolicy()    //解决策略
    );

    //创建任务
    CompletableFuture<String> task1 = CompletableFuture.supplyAsync(()->{
        System.out.println("执行任务一........");
        return "Task1 Sucess";
    },threadPool);
    CompletableFuture<String> task2 = CompletableFuture.supplyAsync(()->{
        System.out.println("执行任务二........");
        return "Task2 Sucess";
    },threadPool);
    CompletableFuture<String> task3 = CompletableFuture.supplyAsync(()->{
        System.out.println("执行任务三........");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Task3 Sucess";
    },threadPool);

    //等待所有任务完成
    CompletableFuture.allOf(task1, task2, task3).join();

    //获取结果
    String s1 = task1.get();
    String s2 = task2.get();
    String s3 = task3.get();
    System.out.println(s1+s2+s3);
    
    threadPool.shutdownNow();
}

 

项目中的使用场景

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值