并发编程(三)CompletableFuturer

并发编程(三)CompletableFuturer

异步化:并行方案得以实施的基础,利用多线程优化性能这个核心方案得以实施的基础。

为什么用CompletableFuturer?

  • 不需要手动维护线程,没有繁琐的手工维护线程的工作。
  • 语义清晰
  • 代码简单并且专注于业务

task is cheap show your code!

package com.zy.concurrent.future;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @author zy1994
 * @Classname CompletableFutureDemo
 * @Date 2019-06-17
 */
public class CompletableFutureDemo {
    public static void main(String[] args) {
        //刷锅 烧水
        CompletableFuture<Void> f1 = 
                CompletableFuture.runAsync(()->{
                    System.out.println("T1 :刷锅....");
                    sleep(1,TimeUnit.SECONDS);
                    System.out.println("T1 :烧开水....");
                    sleep(1,TimeUnit.SECONDS);
                });

        //task 1 洗菜 洗碗 准备面条
        CompletableFuture<String> f2 =
                CompletableFuture.supplyAsync(()->{
                    System.out.println("T2 :洗菜....");
                    sleep(1,TimeUnit.SECONDS);
                    System.out.println("T2 :洗碗....");
                    sleep(1,TimeUnit.SECONDS);
                    System.out.println("T2 :拿面条....");
                    sleep(1,TimeUnit.SECONDS);
                    return "龙须面";
                });
        CompletableFuture<String> f3 =
                f1.thenCombine(f2,(__,tf)->{
                    return "开饭----热腾腾的"+tf;
                });
        System.out.println(f3.join())}

    private static void sleep(int i, TimeUnit seconds) {
          try {
              seconds.sleep(i);
          }catch (Exception e){
              //do something
          }
    }
}

CompletableFuturer四个核心的静态方法

使用默认的线程池 使用的是公共的ForkJoinPool线程池。默认创建的线程数就是cpu的核数。

最好不要使用公共的线程池,最好根据不同的业务创建不同的线程池,防止相互干扰,造成线程饥饿。

public static CompletableFuture<Void> runAsync(Runnable runnable) {
    return asyncRunStage(asyncPool, runnable);
}
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
    return asyncSupplyStage(asyncPool, supplier);
}

使用自定义的线程池

public static CompletableFuture<Void> runAsync(Runnable runnable,
                                               Executor executor) {
    return asyncRunStage(screenExecutor(executor), runnable);
}

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                   Executor executor) {
    return asyncSupplyStage(screenExecutor(executor), supplier);
}

对于异步操作需要关心的两个重点问题

  • 异步操作什么时候结束
  • 异步操作的结果是什么

线程之间的关系

CompletionStage接口

串行

thenApply

public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);

thenAccept

public CompletionStage<Void> thenAccept(Consumer<? super T> action);

thenRun

public CompletionStage<Void> thenRun(Runnable action);

thenCompose

public <U> CompletionStage<U> thenCompose
    (Function<? super T, ? extends CompletionStage<U>> fn);
 CompletableFuture<String> ff = CompletableFuture.supplyAsync(() -> "i Love I")
                .thenApply(v -> v + "NB")
                .thenApply(String::toLowerCase);
        System.out.println(ff.join());

And汇聚

CompletionStage<R> thenCombine(other, fn);
CompletionStage<R> thenCombineAsync(other, fn);
CompletionStage<Void> thenAcceptBoth(other, consumer);
CompletionStage<Void> thenAcceptBothAsync(other, consumer);
CompletionStage<Void> runAfterBoth(other, action);
CompletionStage<Void> runAfterBothAsync(other, action);

or汇聚

CompletionStage applyToEither(other, fn);
CompletionStage applyToEitherAsync(other, fn);
CompletionStage acceptEither(other, consumer);
CompletionStage acceptEitherAsync(other, consumer);
CompletionStage runAfterEither(other, action);
CompletionStage runAfterEitherAsync(other, action);
 CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
            int ss = getRandom(3, 8);
            sleep(ss, TimeUnit.SECONDS);
            return String.valueOf(ss);
        });

        CompletableFuture<String> stringCompletableFuture1 = CompletableFuture.supplyAsync(() -> {
            int ss = getRandom(3, 8);
            sleep(ss, TimeUnit.SECONDS);
            return String.valueOf(ss);
        });
        CompletableFuture<String> stringCompletableFuture2 = stringCompletableFuture.applyToEither(stringCompletableFuture1, s -> s);
        System.out.println(stringCompletableFuture2.join());
    }

	/**
     * 生成开始到结束的一个随机数
     * @param begin
     * @param end
     * @return
     */
    public static int getRandom(int begin,int end){
      return (int)(begin+ Math.random()*(end-begin+1));
    }

CompletionStage处理异常

 public static void exceptionHandler(){
        CompletableFuture<Integer> exceptionally = CompletableFuture.supplyAsync(() -> 1 / 0)
                .exceptionally(e -> {
                    System.out.println(e);
                    return 0;
                }).whenComplete((u,t)->{
                    System.out.println("finally"+t);
                });
    }

你可能感兴趣的:(java,并发编程)