实现异步编程,这个工具类你得掌握!

前言

最近看公司代码,多线程编程用的比较多,其中有对CompletableFuture的使用,所以想写篇文章总结下

在日常的Java8扁平化管理是什么意思项目开发中,CompletableFuture是很强大的并行开宫颈癌发工具,其语法贴近java8的语java模拟器法风格,与stream一起使用也能大大增加代码的简洁性

大家可以多线程池创建应用到工作中,提升设备异常处理接口性能,优化代码

文章首发在公众号(月伴飞鱼),之后同步到个人网站:xiaoflyfish.c工商银行n/

觉得有收获,希望帮忙点赞,转发下哈,谢谢,谢工商银行

基本介绍

CompletableFuture是Java 8新增的一个类,用于异步编程,继承了Futur扁平化设计e和java模拟器Comjava是什么意思pletionStage

这个Future主要具备对请求结果独立处理的功能,CompletionStage用于实现流式处理,实现异步请求的各个阶段组合或链式处理,因此completableFuture能实现整个异步调用接口线程池的核心参数扁平化和流式处理,解决原有Future处理一系列链式异步请求时的复杂编码

实现异步编程,这个工具类你得掌握!

Fjavascriptuture的局限性

1、枸杞Future 的结果在非阻塞的情况下,不能扁平化管理的潜台词执行更进一步的操作

我们知道,使用Future时只能通过isDone()方法判断任务是否完成,或者通过get()方法线程池阻塞线程等待结果返回,它不能非阻扁平化管理通俗解释宫颈癌的情况下,执行更进一步的操作。

2、不能组合多个Future的结果

假设c 异常处理你有google多个Future异步异常处理三步骤任务,你希望最快的任务执行完时,或者所有任务都工龄差一年工资差多少执行完后,进行一java语言java怎么读些其他操作

3、多个Future宫颈癌不能线程池七大核心参数组成链式调用

当异步任务之间有依赖关异常龚俊扁平化管理是什么意思理流程为哪三步系时,Future不能将一个任务的结果传给另一个异步任务,多个F异常处理流程为哪三步ut枸杞ure无法创建链式的工作流。

4、没有异常处理

现在使用CompletableFuture能帮助我们完成上java模拟器面的事情,让我们编写更宫颈癌强大、更优雅的异步程序

扁平化管理是什么意思本使用

创建异步任务

通常可枸杞以使用下面几个CompletableFuture的静态方法创建一个异步任java模拟器

public static CompletableFuture<Void> runAsync(Runnable runnable);              //创建无返回值的异步任务
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor);     //无返回值,可指定线程池(默认使用ForkJoinPool.commonPool)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);           //创建有返回值的异步任务
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor); //有返回值,可指定线程池

使用示例:

Executor executor = Executors.newFixedThreadPool(10);
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    //do something
}, executor);
int poiId = 111;
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
 PoiDTO poi = poiService.loadById(poiId);
  return poi.getName();
});
// Block and get the result of the Future
String poiName = future.get();

使用回调方法

通过线程池的七个参数futur扁平化管理e.get()方法获取异步任务的结果,还是会阻塞的等扁平化图标待任务完成

Compl线程池面试题etableFuture提供了几个苟在神诡世界回调方法,可异常处理流程为哪三步以不阻异常处理流程为哪三步塞主线程,在异步任务完成后自设备异常处理动执行回调方法中的代码

public CompletableFuture<Void> thenRun(Runnable runnable);            //无参数、无返回值
public CompletableFuture<Void> thenAccept(Consumer<? super T> action);         //接受参数,无返回值
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn); //接受参数T,有返回值U

使用示例:

CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello")
                           .thenRun(() -> System.out.println("do other things. 比如异步打印日志或发送消息"));
//如果只想在一个CompletableFuture任务执行完后,进行一些后续的处理,不需要返回值,那么可以用thenRun回调方法来完成。
//如果主线程不依赖thenRun中的代码执行完成,也不需要使用get()方法阻塞主线程。
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello")
                           .thenAccept((s) -> System.out.println(s + " world"));
//输出:Hello world
//回调方法希望使用异步任务的结果,并不需要返回值,那么可以使用thenAccept方法
CompletableFuture<Boolean> future = CompletableFuture.supplyAsync(() -> {
  PoiDTO poi = poiService.loadById(poiId);
  return poi.getMainCategory();
}).thenApply((s) -> isMainPoi(s));   // boolean isMainPoi(int poiId);
future.get();
//希望将异步任务的结果做进一步处理,并需要返回值,则使用thenApply方法。
//如果主线程要获取回调方法的返回,还是要用get()方法阻塞得到

线程池原理合两个异步任务

//thenCompose方法中的异步任务依赖调用该方法的异步任务
public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn); 
//用于两个独立的异步任务都完成的时候
public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other, 
                                              BiFunction<? super T,? super U,? extends V> fn); 

使用示例:

CompletableFuture<List<Integer>> poiFuture = CompletableFuture.supplyAsync(
  () -> poiService.queryPoiIds(cityId, poiId)
);
//第二个任务是返回CompletableFuture的异步方法
CompletableFuture<List<DealGroupDTO>> getDeal(List<Integer> poiIds){
  return CompletableFuture.supplyAsync(() ->  poiService.queryPoiIds(poiIds));
}
//thenCompose
CompletableFuture<List<DealGroupDTO>> resultFuture = poiFuture.thenCompose(poiIds -> getDeal(poiIds));
resultFuture.get();

thenCompose和th线程池的七个参数enApply的功线程池原理能类似,两者区别在于thenComp异常处理员ose线程池的使用异常处理员是干什么的接受一个返回CompletableFuture<U>的Functionjava模拟器,当想从回调方法返回异常处理流程Complet异常处理员ableFuture<U>中直接扁平化管理模式获取结果U时,就用thenCompose

如果使用then工龄越长退休金越多吗Apply,返回结果resultFuture的类型是公积金CompletableFuture<CompletableFuture<List&异常处理员是干什么的lt;DealGroupDTO>>工龄差一年工资差多少>,而不是c 异常处理CompjavaeeletableFuture&工龄差一年工资差多少lt;List&lt异常处理员;DealGroupDTO&gjava是什么意思t;>

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
  .thenCombine(CompletableFuture.supplyAsync(() -> "world"), (s1, s2) -> s1 + s2);
//future.get()

组合多个CompletableFut线程池拒绝策略ure

当需异常处理员是干什么的要多个异java线程池七大核心参数模拟器步任务都完成时,再进行后续处扁平化什么意思理,可以使用allOf方法

CompletableFuture<Void> poiIDTOFuture = CompletableFuture
 .supplyAsync(() -> poiService.loadPoi(poiId))
  .thenAccept(poi -> {
    model.setModelTitle(poi.getShopName());
    //do more thing
  });
CompletableFuture<Void> productFuture = CompletableFuture
 .supplyAsync(() -> productService.findAllByPoiIdOrderByUpdateTimeDesc(poiId))
  .thenAccept(list -> {
    model.setDefaultCount(list.size());
    model.setMoreDesc("more");
  });
//future3等更多异步任务,这里就不一一写出来了
CompletableFuture.allOf(poiIDTOFuture, productFuture, future3, ...).join();  //allOf组合所有异步任务,并使用join获取结果

该方法挺适合C端的业务,比如通过poiId异步线程池拒绝策略的从多java语言个服务拿门店异常处理流程信息,然后组装成自己需要的模型,最后所有门店信息都填充完后返回

这里使用了join方法获取结果,它和get方法java培训一样阻塞的等待任务完成

多个异步任务有任意一个完成时就返回结果,可以使用anyOf方法

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    try {
        TimeUnit.SECONDS.sleep(2);
    } catch (InterruptedException e) {
       throw new IllegalStateException(e);
    }
    return "Result of Future 1";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
       throw new IllegalStateException(e);
    }
    return "Result of Future 2";
});
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
    try {
        TimeUnit.SECONDS.sleep(3);
    } catch (InterruptedException e) {
       throw new IllegalStateException(e);
      return "Result of Future 3";
});
CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2, future3);
System.out.println(anyOfFuture.get()); // Result of Future 2

异常处理

Integer age = -1;
CompletableFuture<Void> maturityFuture = CompletableFuture.supplyAsync(() -> {
  if(age < 0) {
    throw new IllegalArgumentException("Age can not be negative");
  }
  if(age > 18) {
    return "Adult";
  } else {
    return "Child";
  }
}).exceptionally(ex -> {
  System.out.println("Oops! We have an exception - " + ex.getMessage());
  return "Unknown!";
}).thenAccept(s -> System.out.print(s));
//Unkown!

excepjava是什么意思tionally方法可以处理异步任务的异常,在出现异常时,给异步任务链一个工商银行电话人工客服从错误中恢复的机会,线程池拒绝策略可以在这里记录异常或返回一个默认值

使用handler方法也可以处理异常,并且无论线程池七大核心参数是否发生异常它都会被调用

Integer age = -1;
CompletableFuture<String> maturityFuture = CompletableFuture.supplyAsync(() -> {
    if(age < 0) {
        throw new IllegalArgumentException("Age can not be negative");
    }
    if(age > 18) {
        return "Adult";
    } else {
        return "Child";
    }
}).handle((res, ex) -> {
    if(ex != null) {
        System.out.println("Oops! We have an exception - " + ex.getMessage());
        return "Unknown!";
    }
    return res;
});

分片处理

分片和并行处理:分片借助stream实现,然后通过CompletableFuture实现并行执行,最后做数据Java聚合(其实也扁平化图标是strja设备异常处理va培训eam的方法)

CompletableFutur异常处理流程为哪三步e并不提供单独的分片api,但可以借助stream的分片聚合功能实现

举个例子javascript

//请求商品数量过多时,做分批异步处理
List<List<Long>> skuBaseIdsList = ListUtils.partition(skuIdList, 10);//分片
//并行
List<CompletableFuture<List<SkuSales>>> futureList = Lists.newArrayList();
for (List<Long> skuId : skuBaseIdsList) {
  CompletableFuture<List<SkuSales>> tmpFuture = getSkuSales(skuId);
  futureList.add(tmpFuture);
}
//聚合
futureList.stream().map(CompletalbleFuture::join).collent(Collectors.toList());

举个例子

带大家领略下CompletableFuture异步编程的优势

这里我们用Compjava语言letajava编译器bleF工商银行电话人工客服uture实现水泡茶程序

首先还是需要先完成分工方案,在下面的程序中,我们分了3个任务:

  • 任务1负责洗水壶异常处理的关键字、烧开水
  • 任务2负责洗茶壶、洗茶杯和拿茶叶
  • 任务3负责泡茶。其中任务3要等待任务1和任务2都完成后才能开始

实现异步编程,这个工具类你得掌握!

下面是代码实现线程池的使用,你先略过ru异常处理三步骤nAsync()、supplyAs扁平化管理的潜台词ync()、thenCombine()这些不设备异常处理太熟悉的方法,从扁平化异常处理三步骤通俗是什么意思大局上看,你会发现:

  1. 无需手工维护线程,没有繁琐的手java培训工维护线程的工作,给google任务分配线程的工作也不需要我们关注;
  2. 语义更清晰,例生产异常扁平化什么意思处理f3 =线程池拒绝策略 f1.thenCombine(f2, ()->{}) 能够清Go晰地扁平化管理是什么意思表述任务3扁平化管理要等待任务1和任务2都完成后才能开始
  3. 代码更简练并且专注于业务逻辑,几乎所有java面试题代码都是业务逻辑相关的
//任务1:洗水壶->烧开水
CompletableFuture f1 = 
  CompletableFuture.runAsync(()->{
  System.out.println("T1:洗水壶...");
  sleep(1, TimeUnit.SECONDS);
  System.out.println("T1:烧开水...");
  sleep(15, TimeUnit.SECONDS);
});
//任务2:洗茶壶->洗茶杯->拿茶叶
CompletableFuture f2 = 
  CompletableFuture.supplyAsync(()->{
  System.out.println("T2:洗茶壶...");
  sleep(1, TimeUnit.SECONDS);
  System.out.println("T2:洗茶杯...");
  sleep(2, TimeUnit.SECONDS);
  System.out.println("T2:拿茶叶...");
  sleep(1, TimeUnit.SECONDS);
  return "龙井";
});
//任务3:任务1和任务2完成后执行:泡茶
CompletableFuture f3 = 
  f1.thenCombine(f2, (__, tf)->{
    System.out.println("T1:拿到茶叶:" + tf);
    System.out.println("T1:泡茶...");
    return "上茶:" + tf;
  });
//等待任务3执行结果
System.out.println(f3.join());
void sleep(int t, TimeUnit u) {
  try {
    u.sleep(t);
  }catch(InterruptedException e){}
}
// 一次执行结果:
T1:洗水壶...
T2:洗茶壶...
T1:烧开水...
T2:洗茶杯...
T2:拿茶叶...
T1:拿到茶叶:龙井
T1:泡茶...
上茶:龙井

注意事项

1.C异常处理流程ompletableFuture生产异常处理默认线程池是否满足使用

前面提到创建Comjjavascriptava编译器异常处理的关键字pletabl异常处理三步骤eF异常处理uture异步任务的静态方法runAsync和supplyAsync等,可以指定使用的异常处理三步骤线程池,不指定则用CompletableFuture的默认线程池

private static final Executor asyncPool = useCommonPool ?
        ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();

可以看到,Comp枸杞letableFuture默认线程池是调用ForkJoinPool的commonPo生产异常处理ol()方法创建,这个默认线程池的核心线程数量根据CPU核数而定google,公式为Runtime.getRuntime().availableProcessors() - 1,以4核双槽CPU为例,核心线扁平化组织结构程数量就是4*2-1=7

这样的设置满足CPU密集型的应用,但对于业务都线程池是IO密集型的应用来说,是有风险的,当qps较高时,线程数量可能就异常处理三步骤设的太少了,会导致线上故障

所以可以根据业务情况自定义线程池使用

2.get设置超时时间不能串行get,不然会导致接口延时线程数量*超时时间

最后

写文章画图不易,喜欢的话,希望帮忙点赞,转发下哈,谢谢

微信搜索:月伴飞鱼,线程池的核心参数交个朋友

发表评论

提供最优质的资源集合

立即查看 了解详情