java 异步编排_Java线程池与异步编排

Java创建线程的四种方式

1.继承Thread类实现多线程

public class MyThread extendsThread {publicMyThread() {

}public voidrun() {for(int i=0;i<10;i++) {

System.out.println(Thread.currentThread()+":"+i);

}

}public static voidmain(String[] args) {

MyThread mThread1=newMyThread();

MyThread mThread2=newMyThread();

MyThread myThread3=newMyThread();

mThread1.start();

mThread2.start();

myThread3.start();

}

}

2.覆写Runnable()接口实现多线程,而后同样覆写run().推荐此方式

public class MyThread implementsRunnable{public static int count=20;public voidrun() {while(count>0) {try{

Thread.sleep(200);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"-当前剩余票数:"+count--);

}

}public static voidmain(String[] args) {

MyThread Thread1=newMyThread();

Thread mThread1=new Thread(Thread1,"线程1");

Thread mThread2=new Thread(Thread1,"线程2");

Thread mThread3=new Thread(Thread1,"线程3");

mThread1.start();

mThread2.start();

myThread3.start();

}

}

继承Thread和实现Runnable接口的区别:

a.实现Runnable接口避免多继承局限

b.实现Runnable()可以更好的体现共享的概念

3.覆写Callable接口实现多线程JDK1.5

packagecom.xieh;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.FutureTask;/*** 实现Callable接口创建多线程Callable接口的泛型是返回值类型

*

*@author谢辉

**/

public class ThreadTest implements Callable{

@Overridepublic Integer call() throwsException {//TODO Auto-generated method stub

System.out.println("当前线程:" +Thread.currentThread().getName());int i = 10 / 2;

System.out.println("结果是:" +i);returni;

}public static void main(String[] args) throwsInterruptedException, ExecutionException {

System.out.println("main--start");

Callable callable = newThreadTest();

FutureTask futureTask = new FutureTask(callable);

Thread thread= newThread(futureTask);

thread.start();//等待线程执行完,获取返回结果:注意:获取返回结果是个阻塞的操作!!

Integer integer =futureTask.get();

System.out.println("线程返回的结果:" +integer);

System.out.println("main--end.");

}

}

51b4e34081fb123d775ccd7cd29c16b0.png

4.通过线程池启动多线程

通过Executor 的工具类可以创建三种类型的普通线程池:

FixThreadPool(int n); 固定大小的线程池

使用于为了满足资源管理需求而需要限制当前线程数量的场合。使用于负载比较重的服务器。

packagecom.xieh;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.Future;public classThreadPool {//创建一个固定大小的线程池

public static ExecutorService ex = Executors.newFixedThreadPool(5);public static voidmain(String[] args) {for (int i = 0; i < 2; i++) {

Future> submit = ex.submit(newRunnable() {

@Overridepublic voidrun() {for (int j = 0; j < 3; j++) {

System.out.println(Thread.currentThread().getName()+ "---" +j);

}

}

});

}

ex.execute(newRunnable() {

@Overridepublic voidrun() {//TODO Auto-generated method stub

System.out.println(Thread.currentThread().getName() + "计算结果:" + 10 / 2);

}

});

ex.shutdown();

}

}

b48d6831b25db91647834d84bbd36f5b.png

SingleThreadPoolExecutor :单线程池

需要保证顺序执行各个任务的场景

packagecom.xieh;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.Future;public classThreadPool {public static voidmain(String[] args) {//SingleThreadPoolExecutor :单线程池

ExecutorService ex =Executors.newSingleThreadExecutor();for (int i = 0; i < 2; i++) {

Future> submit = ex.submit(newRunnable() {

@Overridepublic voidrun() {for (int j = 0; j < 3; j++) {

System.out.println(Thread.currentThread().getName()+ "---" +j);

}

}

});

}

ex.shutdown();

}

}

954d89351c1a0534cfc1e204b2d6eb02.png

CashedThreadPool(); 缓存线程池

当提交任务速度高于线程池中任务处理速度时,缓存线程池会不断的创建线程

适用于提交短期的异步小程序,以及负载较轻的服务器

packagecom.xieh;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.Future;public classThreadPool {public static voidmain(String[] args) {//CashedThreadPool(); 缓存线程池

ExecutorService ex =Executors.newCachedThreadPool();for (int i = 0; i < 3; i++) {

Future> submit = ex.submit(newRunnable() {

@Overridepublic voidrun() {for (int j = 0; j < 3; j++) {

System.out.println(Thread.currentThread().getName()+ "---" +j);

}

}

});

}

ex.shutdown();

}

}

444a2d4c45480ed33cac9846680263a1.png

execute()和submit()方法

1、execute(),执行一个任务,没有返回值。

2、submit(),提交一个线程任务,有返回值。

submit(Callable task)能获取到它的返回值,通过future.get()获取(阻塞直到任务执行完)。一般使用FutureTask+Callable配合使用(IntentService中有体现)。

submit(Runnable task, T result)能通过传入的载体result间接获得线程的返回值。

submit(Runnable task)则是没有返回值的,就算获取它的返回值也是null。

Future.get方法会使取结果的线程进入阻塞状态,知道线程执行完成之后,唤醒取结果的线程,然后返回结果。

线程池ThreadPoolExecutor详解

这个类的构造函数如下:

public ThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime,

TimeUnit unit,

BlockingQueueworkQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize<= 0 ||maximumPoolSize< corePoolSize ||keepAliveTime< 0)throw newIllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw newNullPointerException();this.corePoolSize =corePoolSize;this.maximumPoolSize =maximumPoolSize;this.workQueue =workQueue;this.keepAliveTime =unit.toNanos(keepAliveTime);this.threadFactory =threadFactory;this.handler =handler;

}

7大参数详解:

dbee8af59363e734bf34a0ec131e9726.png

corePoolSize

核心线程数。在创建线程池之后,默认情况下线程池中并没有任何的线程,而是等待任务到来才创建线程去执行任务,当线程池中的线程数目达到 corePoolSize后,新来的任务将会被添加到缓存队列中,也就是那个workQueue,除非调用 ThreadPoolExecutor#prestartAllCoreThreads() 方法或者是 ThreadPoolExecutor # prestartCoreThread() 方法(从这两个方法的名字就可以看出是预创建线程的意思,即在没有任务到来之前就创建corePoolSize个线程或一个线程)。

PS:很多人不知道这个数该填多少合适,其实也不必特别纠结,根据实际情况填写就好,实在不知道,就按照阿里工程师的写法取下列值就好了:

int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();

maximumPoolSize

线程池中的最大线程数。表示线程池中最多可以创建多少个线程,很多人以为它的作用是这样的:”当线程池中的任务数超过 corePoolSize 后,线程池会继续创建线程,直到线程池中的线程数小于maximumPoolSize“,其实这种理解是完全错误的。它真正的作用是:当线程池中的线程数等于 corePoolSize 并且 workQueue 已满,这时就要看当前线程数是否大于 maximumPoolSize,如果小于maximumPoolSize 定义的值,则会继续创建线程去执行任务, 否则将会调用去相应的任务拒绝策略来拒绝这个任务。另外超过 corePoolSize的线程被称做"Idle Thread", 这部分线程会有一个最大空闲存活时间(keepAliveTime),如果超过这个空闲存活时间还没有任务被分配,则会将这部分线程进行回收。

keepAliveTime

控制"idle Thread"的空闲存活时间。这个idle Thread就是上面提到的超过 corePoolSize 后新创建的那些线程,默认情况下,只有当线程池中的线程数大于corePoolSize,且这些"idle Thread"并没有被分配任务时,这个参数才会起作用。另外,如果调用了 ThreadPoolExecutor#allowCoreThreadTimeOut(boolean) 的方法,在线程池中的线程数不大于corePoolSize,且这些core Thread 也没有被分配任务时,keepAliveTime 参数也会起作用。

unit

参数keepAliveTime的时间单位,共7种取值,在TimeUtil中定义:

TimeUnit.DAYS; //天

TimeUnit.HOURS; //小时

TimeUnit.MINUTES; //分钟

TimeUnit.SECONDS; //秒

TimeUnit.MILLISECONDS; //毫秒

TimeUnit.MICROSECONDS; //微妙

TimeUnit.NANOSECONDS; //纳秒

workQueue

阻塞队列。如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到该队列当中,注意只要超过了 corePoolSize 就会把任务添加到该缓存队列,添加可能成功也可能不成功,如果成功的话就会等待空闲线程去执行该任务,若添加失败(一般是队列已满),就会根据当前线程池的状态决定如何处理该任务(若线程数 < maximumPoolSize 则新建线程;若线程数 >= maximumPoolSize,则会根据拒绝策略做具体处理)。

常用的阻塞队列有:

1)ArrayBlockingQueue       //基于数组的先进先出队列,此队列创建时必须指定大小;

2)LinkedBlockingQueue      //基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;

3)synchronousQueue        //这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。

threadFactory

线程工厂。用来为线程池创建线程,当我们不指定线程工厂时,线程池内部会调用Executors.defaultThreadFactory()创建默认的线程工厂,其后续创建的线程优先级都是Thread.NORM_PRIORITY。如果我们指定线程工厂,我们可以对产生的线程进行一定的操作。

handler

拒绝执行策略。当线程池的缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:

ThreadPoolExecutor.AbortPolicy:         // 丢弃任务并抛出RejectedExecutionException异常。

ThreadPoolExecutor.DiscardPolicy:       // 也是丢弃任务,但是不抛出异常。

ThreadPoolExecutor.DiscardOldestPolicy:   // 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

ThreadPoolExecutor.CallerRunsPolicy:     // 由调用线程处理该任务

05c532cf478eeb21e6e241a84888e090.png

771f78d1ff4e81ebb0e3abbda26407fd.png

d5d0b5ca0ab6413afe35ba16aeb36e2a.png

95736294b20a22a752e8946a60876b0f.png

CompletableFuture异步编排

1、runAsync 和 supplyAsync方法

CompletableFuture 提供了四个静态方法来创建一个异步操作:

public static CompletableFuturerunAsync(Runnable runnable)public static CompletableFuturerunAsync(Runnable runnable, Executor executor)public static CompletableFuture supplyAsync(Suppliersupplier)public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)

没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。以下所有的方法都类同。

runAsync方法不支持返回值。

supplyAsync方法可以支持返回值。

runAsync方法示例:

packagecom.xieh;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.LinkedBlockingDeque;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;public classCompletableFutureTest {public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,new LinkedBlockingDeque(1000), Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());public static void main(String[] args) throwsInterruptedException, ExecutionException {

System.out.println("main---start");//没有返回值

CompletableFuture future = CompletableFuture.runAsync(() ->{

System.out.println("当前线程:" +Thread.currentThread().getName());int i = 10 / 2;

System.out.println("计算结果:" +i);

}, executorService);//什么都不返回,调用get方法,就变成了阻塞操作!//future.get();

System.out.println("main---end");

executorService.shutdown();

}

}

4387833e26092c62babc227c531baf60.png

supplyAsync方法示例:

packagecom.xieh;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.LinkedBlockingDeque;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;public classCompletableFutureTest {public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,new LinkedBlockingDeque(1000), Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());public static void main(String[] args) throwsInterruptedException, ExecutionException {

System.out.println("main---start");//有返回值

CompletableFuture future = CompletableFuture.supplyAsync(() ->{

System.out.println("当前线程:" +Thread.currentThread().getName());int i = 10 / 2;

System.out.println("计算结果:" +i);returni;

}, executorService);//获取返回结果,调用get方法,就变成了阻塞操作!

Integer integer =future.get();

System.out.println("main---end:" +integer);

executorService.shutdown();

}

}

afae4a0647ded9e99796f5f79c57a7b6.png

2、计算结果完成时的回调方法

当CompletableFuture的计算结果完成,或者抛出异常的时候,可以执行特定的Action。主要是下面的方法:

public CompletableFuture whenComplete(BiConsumer super T,? super Throwable>action)public CompletableFuture whenCompleteAsync(BiConsumer super T,? super Throwable>action)public CompletableFuture whenCompleteAsync(BiConsumer super T,? super Throwable>action, Executor executor)public CompletableFuture exceptionally(Function fn)

可以看到Action的类型是BiConsumer super T,? super Throwable>它可以处理正常的计算结果,或者异常情况。

whenComplete 和 whenCompleteAsync 的区别:

whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。

whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。

135a67cfa8a9bc90e96433e9396a47f0.png

runAsync方法计算结果完成时的后续操作示例:

packagecom.xieh;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.LinkedBlockingDeque;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;importjava.util.function.BiConsumer;importjava.util.function.Function;public classCompletableFutureTest {public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,new LinkedBlockingDeque(1000), Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());public static void main(String[] args) throwsInterruptedException, ExecutionException {

System.out.println("main---start");

CompletableFuture future = CompletableFuture.runAsync(() ->{

System.out.println("当前线程:" +Thread.currentThread().getName());int i = 10 / 0;

System.out.println("计算结果:" +i);

}, executorService);

future.whenComplete(new BiConsumer() {

@Overridepublic voidaccept(Void t, Throwable action) {

System.out.println("whenComplete执行完成!" +Thread.currentThread().getName());

}

});

future.whenCompleteAsync(new BiConsumer() {

@Overridepublic voidaccept(Void t, Throwable action) {

System.out.println("whenCompleteAsync执行完成!" +Thread.currentThread().getName());

}

});

future.exceptionally(new Function() {

@OverridepublicVoid apply(Throwable t) {

System.out.println("执行失败!" +t.getMessage());return null;

}

});//获取返回结果,调用get方法,就变成了阻塞操作!//future.get();

System.out.println("main---end:");

executorService.shutdown();

}

}

b8e8766459bef851098b71f4aa2fad27.png

supplyAsync方法计算结果完成时的后续操作示例:

packagecom.xieh;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.LinkedBlockingDeque;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;public classCompletableFutureTest {public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,new LinkedBlockingDeque(1000), Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());public static void main(String[] args) throwsInterruptedException, ExecutionException {

System.out.println("main---start");

CompletableFuture future = CompletableFuture.supplyAsync(() ->{

System.out.println("当前线程:" +Thread.currentThread().getName());int i = 10 / 0;

System.out.println("计算结果:" +i);returni;

}, executorService).whenComplete((result, exception)->{//虽然能得到异常信息,但是无法修改返回数据

System.out.println("whenComplete异步任务完成了,结果是:" + result + ";异常是:" +exception);

}).whenCompleteAsync((result, exception)->{

System.out.println("whenCompleteAsync异步任务完成了,结果是:" + result + ";异常是:" +exception);

}).exceptionally(throwable->{//如果执行失败,可以设置默认返回值

return 10;

});//获取返回结果

Integer integer =future.get();

System.out.println("main---end:" +integer);

executorService.shutdown();

}

}

e6d74c45cd538347d8d0f80e6626f022.png

3、 handle 方法

handle 是执行任务完成时对结果的处理。

handle 方法和 thenApply 方法处理方式基本一样。不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法。

代码示例:

packagecom.xieh;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.LinkedBlockingDeque;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;public classCompletableFutureTest {public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,new LinkedBlockingDeque(1000), Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());public static void main(String[] args) throwsInterruptedException, ExecutionException {

System.out.println("main---start");

CompletableFuture future = CompletableFuture.supplyAsync(() ->{

System.out.println("当前线程:" +Thread.currentThread().getName());int i = 10 / 0;

System.out.println("计算结果:" +i);returni;

}, executorService).whenComplete((result, exception)->{//虽然能得到异常信息,但是无法修改返回数据

System.out.println("whenComplete异步任务完成了,结果是:" + result + ";异常是:" +exception);

}).whenCompleteAsync((result, exception)->{

System.out.println("whenCompleteAsync异步任务完成了,结果是:" + result + ";异常是:" +exception);

}).handle((result, throwable)->{if (result != null) {return result * 2;

}if (throwable != null) {return 1;

}return 0;//注意:handle与exceptionally都可以控制返回值,谁先被调用就以谁的为准(先被调用者的返回值为准)

}).exceptionally(throwable ->{//如果执行失败,可以设置默认返回值

return 10;

});//获取返回结果

Integer integer =future.get();

System.out.println("main---end:" +integer);

executorService.shutdown();

}

}

49f9768dc8665c1b1c1e065274fcc68f.png

4、线程串行化

thenApply 方法:当一个线程依赖另一个线程时,可以使用 thenApply 方法来把这两个线程串行化。

thenAccept 消费处理结果:接收任务的处理结果,并消费处理,无返回结果。

thenRun 方法:跟 thenAccept 方法不一样的是,不关心任务的处理结果。只要上面的任务执行完成,就开始执行 thenRun 。

public CompletableFuture thenApply(Function super T,? extends U>fn)public CompletableFuture thenApplyAsync(Function super T,? extends U>fn)public CompletableFuture thenApplyAsync(Function super T,? extends U>fn, Executor executor)public CompletionStage thenAccept(Consumer super T>action);public CompletionStage thenAcceptAsync(Consumer super T>action);public CompletionStage thenAcceptAsync(Consumer super T>action,Executor executor);public CompletionStagethenRun(Runnable action);public CompletionStagethenRunAsync(Runnable action);public CompletionStage thenRunAsync(Runnable action,Executor executor);

b3f59aae44dce7a3860ffb12114df8bd.png

thenRun代码示例:

packagecom.xieh;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.LinkedBlockingDeque;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;public classCompletableFutureTest {public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,new LinkedBlockingDeque(1000), Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());public static void main(String[] args) throwsInterruptedException, ExecutionException {

System.out.println("main---start");//thenRun不能获取上一步的执行结果

CompletableFuture future = CompletableFuture.supplyAsync(() ->{

System.out.println("当前线程:" +Thread.currentThread().getName());int i = 10 / 2;

System.out.println("计算结果:" +i);returni;

}, executorService).thenRunAsync(()->{

System.out.println("任务2启动了...");

}, executorService);

System.out.println("main---end:");

executorService.shutdown();

}

}

533cdd3d8afdd922057882fdecaa6c66.png

thenAccept代码示例:

packagecom.xieh;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.LinkedBlockingDeque;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;public classCompletableFutureTest {public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,new LinkedBlockingDeque(1000), Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());public static void main(String[] args) throwsInterruptedException, ExecutionException {

System.out.println("main---start");//thenAccept能获取到上一步的结果,但是无返回值

CompletableFuture future = CompletableFuture.supplyAsync(() ->{

System.out.println("当前线程:" +Thread.currentThread().getName());int i = 10 / 2;

System.out.println("计算结果:" +i);returni;

}, executorService).thenAcceptAsync((result)->{

System.out.println("任务2启动了,上一步的结果是:" +result);

}, executorService);

System.out.println("main---end:");

executorService.shutdown();

}

}

ca6072a86eb523fda1c3cdcb62299472.png

thenApply代码示例:

packagecom.xieh;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.LinkedBlockingDeque;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;public classCompletableFutureTest {public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,new LinkedBlockingDeque(1000), Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());public static void main(String[] args) throwsInterruptedException, ExecutionException {

System.out.println("main---start");//thenApply能获取到上一步的结果,可以有返回值

CompletableFuture future = CompletableFuture.supplyAsync(() ->{

System.out.println("当前线程:" +Thread.currentThread().getName());int i = 10 / 2;

System.out.println("计算结果:" +i);returni;

}, executorService).thenApplyAsync(result->{

System.out.println("任务2开启了,上一步的结果是:" +result);return "thenApplyAsync的新结果";

}, executorService);

String string=future.get();

System.out.println("main---end:" +string);

executorService.shutdown();

}

}

bc9ee7105bf9bbc3ae25670c9a89d021.png

5、任务合并

thenCombine:thenCombine 会把 两个 CompletionStage 的任务都执行完成后,把两个任务的结果一块交给 thenCombine 来处理。

thenAcceptBoth:当两个CompletionStage都执行完成后,把结果一块交给thenAcceptBoth来进行消耗。

thenCompose:thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作。

applyToEither:两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的转化操作。

acceptEither:两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的消耗操作。

runAfterEither:两个CompletionStage,任何一个完成了都会执行下一步的操作(Runnable)。

runAfterBoth:两个CompletionStage,都完成了计算才会执行下一步的操作(Runnable)。

public CompletionStage thenCombine(CompletionStage extends U> other,BiFunction super T,? super U,? extends V>fn);public CompletionStage thenCombineAsync(CompletionStage extends U> other,BiFunction super T,? super U,? extends V>fn);public CompletionStage thenCombineAsync(CompletionStage extends U> other,BiFunction super T,? super U,? extends V>fn,Executor executor);public CompletionStage thenAcceptBoth(CompletionStage extends U> other,BiConsumer super T, ? super U>action);public CompletionStage thenAcceptBothAsync(CompletionStage extends U> other,BiConsumer super T, ? super U>action);public CompletionStage thenAcceptBothAsync(CompletionStage extends U> other,BiConsumer super T, ? super U>action, Executor executor);public CompletableFuture thenCompose(Function super T, ? extends CompletionStage>fn);public CompletableFuture thenComposeAsync(Function super T, ? extends CompletionStage>fn) ;public CompletableFuture thenComposeAsync(Function super T, ? extends CompletionStage>fn, Executor executor) ;public CompletionStage applyToEither(CompletionStage extends T> other,Function super T, U>fn);public CompletionStage applyToEitherAsync(CompletionStage extends T> other,Function super T, U>fn);public CompletionStage applyToEitherAsync(CompletionStage extends T> other,Function super T, U>fn,Executor executor);public CompletionStage acceptEither(CompletionStage extends T> other,Consumer super T>action);public CompletionStage acceptEitherAsync(CompletionStage extends T> other,Consumer super T>action);public CompletionStage acceptEitherAsync(CompletionStage extends T> other,Consumer super T>action,Executor executor);public CompletionStage runAfterEither(CompletionStage>other,Runnable action);public CompletionStage runAfterEitherAsync(CompletionStage>other,Runnable action);public CompletionStage runAfterEitherAsync(CompletionStage>other,Runnable action,Executor executor);public CompletionStage runAfterBoth(CompletionStage>other,Runnable action);public CompletionStage runAfterBothAsync(CompletionStage>other,Runnable action);public CompletionStage runAfterBothAsync(CompletionStage> other,Runnable action,Executor executor);

thenCombine代码示例:

private static void thenCombine() throwsException {

CompletableFuture future1 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicString get() {return "hello";

}

});

CompletableFuture future2 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicString get() {return "hello";

}

});

CompletableFuture result = future1.thenCombine(future2, new BiFunction() {

@OverridepublicString apply(String t, String u) {return t+" "+u;

}

});

System.out.println(result.get());

}

thenAcceptBoth代码示例:

private static void thenAcceptBoth() throwsException {

CompletableFuture f1 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);try{

TimeUnit.SECONDS.sleep(t);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("f1="+t);returnt;

}

});

CompletableFuture f2 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);try{

TimeUnit.SECONDS.sleep(t);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("f2="+t);returnt;

}

});

f1.thenAcceptBoth(f2,new BiConsumer() {

@Overridepublic voidaccept(Integer t, Integer u) {

System.out.println("f1="+t+";f2="+u+";");

}

});

}

thenCompose代码示例:

private static void thenCompose() throwsException {

CompletableFuture f = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);

System.out.println("t1="+t);returnt;

}

}).thenCompose(new Function>() {

@Overridepublic CompletionStageapply(Integer param) {return CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = param *2;

System.out.println("t2="+t);returnt;

}

});

}

});

System.out.println("thenCompose result : "+f.get());

}

applyToEither 代码示例:

private static void applyToEither() throwsException {

CompletableFuture f1 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);try{

TimeUnit.SECONDS.sleep(t);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("f1="+t);returnt;

}

});

CompletableFuture f2 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);try{

TimeUnit.SECONDS.sleep(t);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("f2="+t);returnt;

}

});

CompletableFuture result = f1.applyToEither(f2, new Function() {

@OverridepublicInteger apply(Integer t) {

System.out.println(t);return t * 2;

}

});

System.out.println(result.get());

}

acceptEither代码示例:

private static void acceptEither() throwsException {

CompletableFuture f1 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);try{

TimeUnit.SECONDS.sleep(t);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("f1="+t);returnt;

}

});

CompletableFuture f2 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);try{

TimeUnit.SECONDS.sleep(t);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("f2="+t);returnt;

}

});

f1.acceptEither(f2,new Consumer() {

@Overridepublic voidaccept(Integer t) {

System.out.println(t);

}

});

}

runAfterEither代码示例:

private static void runAfterEither() throwsException {

CompletableFuture f1 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);try{

TimeUnit.SECONDS.sleep(t);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("f1="+t);returnt;

}

});

CompletableFuture f2 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);try{

TimeUnit.SECONDS.sleep(t);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("f2="+t);returnt;

}

});

f1.runAfterEither(f2,newRunnable() {

@Overridepublic voidrun() {

System.out.println("上面有一个已经完成了。");

}

});

}

runAfterBoth代码示例:

private static void runAfterBoth() throwsException {

CompletableFuture f1 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);try{

TimeUnit.SECONDS.sleep(t);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("f1="+t);returnt;

}

});

CompletableFuture f2 = CompletableFuture.supplyAsync(new Supplier() {

@OverridepublicInteger get() {int t = new Random().nextInt(3);try{

TimeUnit.SECONDS.sleep(t);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("f2="+t);returnt;

}

});

f1.runAfterBoth(f2,newRunnable() {

@Overridepublic voidrun() {

System.out.println("上面两个任务都执行完成了。");

}

});

}

参考文章:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值