• Java线程池与异步编排


    Java创建线程的四种方式

    1.继承Thread类实现多线程

    public class MyThread extends Thread {
        public MyThread() {
            
        }
        public void run() {
            for(int i=0;i<10;i++) {
                System.out.println(Thread.currentThread()+":"+i);
            }
        }
        public static void main(String[] args) {
            MyThread mThread1=new MyThread();
            MyThread mThread2=new MyThread();
            MyThread myThread3=new MyThread();
            mThread1.start();
            mThread2.start();
            myThread3.start();
        }
    }

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

    public class MyThread implements Runnable{
        public static int count=20;
        public void run() {
            while(count>0) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"-当前剩余票数:"+count--);
            }
        }
        public static void main(String[] args) {
            MyThread Thread1=new MyThread();
            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

    package com.xieh;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    /**
     * 实现Callable接口创建多线程Callable<V>接口的泛型是返回值类型
     * 
     * @author 谢辉
     *
     */
    public class ThreadTest implements Callable<Integer> {
    
        @Override
        public Integer call() throws Exception {
            // TODO Auto-generated method stub
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 10 / 2;
            System.out.println("结果是:" + i);
            return i;
        }
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println("main--start");
    
            Callable<Integer> callable = new ThreadTest();
            FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);
    
            Thread thread = new Thread(futureTask);
            thread.start();
            // 等待线程执行完,获取返回结果:注意:获取返回结果是个阻塞的操作!!
            Integer integer = futureTask.get();
            System.out.println("线程返回的结果:" + integer);
    
            System.out.println("main--end.");
    
        }
    
    }

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

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

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

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

    package com.xieh;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class ThreadPool {
        // 创建一个固定大小的线程池
        public static ExecutorService ex = Executors.newFixedThreadPool(5);
    
        public static void main(String[] args) {
            for (int i = 0; i < 2; i++) {
                Future<?> submit = ex.submit(new Runnable() {
    
                    @Override
                    public void run() {
                        for (int j = 0; j < 3; j++) {
                            System.out.println(Thread.currentThread().getName() + "---" + j);
                        }
    
                    }
                });
            }
    
            ex.execute(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    System.out.println(Thread.currentThread().getName() + "计算结果:" + 10 / 2);
    
                }
            });
    
            ex.shutdown();
    
        }
    
    }

    SingleThreadPoolExecutor :单线程池

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

    package com.xieh;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class ThreadPool {
        public static void main(String[] args) {
            // SingleThreadPoolExecutor :单线程池
            ExecutorService ex = Executors.newSingleThreadExecutor();
    
            for (int i = 0; i < 2; i++) {
                Future<?> submit = ex.submit(new Runnable() {
    
                    @Override
                    public void run() {
                        for (int j = 0; j < 3; j++) {
                            System.out.println(Thread.currentThread().getName() + "---" + j);
                        }
    
                    }
                });
            }
            ex.shutdown();
        }
    
    }

    CashedThreadPool(); 缓存线程池

    当提交任务速度高于线程池中任务处理速度时,缓存线程池会不断的创建线程
     适用于提交短期的异步小程序,以及负载较轻的服务器

    package com.xieh;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class ThreadPool {
        public static void main(String[] args) {
            // CashedThreadPool(); 缓存线程池
            ExecutorService ex = Executors.newCachedThreadPool();
    
            for (int i = 0; i < 3; i++) {
                Future<?> submit = ex.submit(new Runnable() {
    
                    @Override
                    public void run() {
                        for (int j = 0; j < 3; j++) {
                            System.out.println(Thread.currentThread().getName() + "---" + j);
                        }
    
                    }
                });
            }
            ex.shutdown();
        }
    
    }

    execute()和submit()方法

    1、execute(),执行一个任务,没有返回值。
    2、submit(),提交一个线程任务,有返回值。
    submit(Callable<T> task)能获取到它的返回值,通过future.get()获取(阻塞直到任务执行完)。一般使用FutureTask+Callable配合使用(IntentService中有体现)。

    submit(Runnable task, T result)能通过传入的载体result间接获得线程的返回值。
    submit(Runnable task)则是没有返回值的,就算获取它的返回值也是null。

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

    线程池ThreadPoolExecutor详解

    这个类的构造函数如下:

    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler) {
            if (corePoolSize < 0 ||
                maximumPoolSize <= 0 ||
                maximumPoolSize < corePoolSize ||
                keepAliveTime < 0)
                throw new IllegalArgumentException();
            if (workQueue == null || threadFactory == null || handler == null)
                throw new NullPointerException();
            this.corePoolSize = corePoolSize;
            this.maximumPoolSize = maximumPoolSize;
            this.workQueue = workQueue;
            this.keepAliveTime = unit.toNanos(keepAliveTime);
            this.threadFactory = threadFactory;
            this.handler = handler;
        }

    7大参数详解:

    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:      // 由调用线程处理该任务

     

     

    CompletableFuture异步编排

    1、runAsync 和 supplyAsync方法

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

    public static CompletableFuture<Void> runAsync(Runnable runnable)
    public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

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

    • runAsync方法不支持返回值。
    • supplyAsync方法可以支持返回值。
    runAsync方法示例:
    package com.xieh;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class CompletableFutureTest {
        public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(1000), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println("main---start");
            // 没有返回值
            CompletableFuture<Void> 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();
        }
    
    }

    supplyAsync方法示例:

    package com.xieh;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class CompletableFutureTest {
        public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(1000), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println("main---start");
    
            // 有返回值
            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getName());
                int i = 10 / 2;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService);
    
            // 获取返回结果,调用get方法,就变成了阻塞操作!
            Integer integer = future.get();
            System.out.println("main---end:" + integer);
            executorService.shutdown();
        }
    
    }

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

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

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

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

    whenComplete 和 whenCompleteAsync 的区别:
    whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
    whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。

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

    package com.xieh;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    import java.util.function.BiConsumer;
    import java.util.function.Function;
    
    public class CompletableFutureTest {
        public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(1000), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println("main---start");
    
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getName());
                int i = 10 / 0;
                System.out.println("计算结果:" + i);
    
            }, executorService);
            
            future.whenComplete(new BiConsumer<Void, Throwable>() {
                @Override
                public void accept(Void t, Throwable action) {
                    System.out.println("whenComplete执行完成!" + Thread.currentThread().getName());
                }
    
            });
            
            future.whenCompleteAsync(new BiConsumer<Void, Throwable>() {
                @Override
                public void accept(Void t, Throwable action) {
                    System.out.println("whenCompleteAsync执行完成!" + Thread.currentThread().getName());
                }
    
            });
            
            future.exceptionally(new Function<Throwable, Void>() {
                @Override
                public Void apply(Throwable t) {
                    System.out.println("执行失败!" + t.getMessage());
                    return null;
                }
            });
    
            // 获取返回结果,调用get方法,就变成了阻塞操作!
            // future.get();
            System.out.println("main---end:");
            executorService.shutdown();
        }
    
    }

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

    package com.xieh;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class CompletableFutureTest {
        public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(1000), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println("main---start");
    
            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getName());
                int i = 10 / 0;
                System.out.println("计算结果:" + i);
                return i;
            }, 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();
        }
    
    }

    3、 handle 方法

    handle 是执行任务完成时对结果的处理。
    handle 方法和 thenApply 方法处理方式基本一样。不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法。
    代码示例:
    package com.xieh;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class CompletableFutureTest {
        public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(1000), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println("main---start");
    
            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getName());
                int i = 10 / 0;
                System.out.println("计算结果:" + i);
                return i;
            }, 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();
        }
    
    }

    4、线程串行化

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

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

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

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

     thenRun代码示例:

    package com.xieh;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class CompletableFutureTest {
        public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(1000), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println("main---start");
    
            // thenRun不能获取上一步的执行结果
            CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getName());
                int i = 10 / 2;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).thenRunAsync(() -> {
                System.out.println("任务2启动了...");
            }, executorService);
    
            System.out.println("main---end:");
            executorService.shutdown();
        }
    
    }

    thenAccept代码示例:

    package com.xieh;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class CompletableFutureTest {
        public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(1000), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println("main---start");
    
            // thenAccept能获取到上一步的结果,但是无返回值
            CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getName());
                int i = 10 / 2;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).thenAcceptAsync((result) -> {
                System.out.println("任务2启动了,上一步的结果是:" + result);
            }, executorService);
    
            System.out.println("main---end:");
            executorService.shutdown();
        }
    
    }

    thenApply代码示例:

    package com.xieh;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class CompletableFutureTest {
        public static ExecutorService executorService = new ThreadPoolExecutor(5, 100, 3L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(1000), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println("main---start");
    
            // thenApply能获取到上一步的结果,可以有返回值
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getName());
                int i = 10 / 2;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).thenApplyAsync(result -> {
                System.out.println("任务2开启了,上一步的结果是:" + result);
                return "thenApplyAsync的新结果";
            }, executorService);
    
            String string = future.get();
            System.out.println("main---end:" + string);
            executorService.shutdown();
        }
    
    }

    5、任务合并

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

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

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

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

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

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

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

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

    thenCombine代码示例:

    private static void thenCombine() throws Exception {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(new Supplier<String>() {
            @Override
            public String get() {
                return "hello";
            }
        });
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(new Supplier<String>() {
            @Override
            public String get() {
                return "hello";
            }
        });
        CompletableFuture<String> result = future1.thenCombine(future2, new BiFunction<String, String, String>() {
            @Override
            public String apply(String t, String u) {
                return t+" "+u;
            }
        });
        System.out.println(result.get());
    }

    thenAcceptBoth代码示例:

    private static void thenAcceptBoth() throws Exception {
        CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f1="+t);
                return t;
            }
        });
            
        CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f2="+t);
                return t;
            }
        });
        f1.thenAcceptBoth(f2, new BiConsumer<Integer, Integer>() {
            @Override
            public void accept(Integer t, Integer u) {
                System.out.println("f1="+t+";f2="+u+";");
            }
        });
    }

    thenCompose代码示例:

    private static void thenCompose() throws Exception {
            CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new Supplier<Integer>() {
                @Override
                public Integer get() {
                    int t = new Random().nextInt(3);
                    System.out.println("t1="+t);
                    return t;
                }
            }).thenCompose(new Function<Integer, CompletionStage<Integer>>() {
                @Override
                public CompletionStage<Integer> apply(Integer param) {
                    return CompletableFuture.supplyAsync(new Supplier<Integer>() {
                        @Override
                        public Integer get() {
                            int t = param *2;
                            System.out.println("t2="+t);
                            return t;
                        }
                    });
                }
                
            });
            System.out.println("thenCompose result : "+f.get());
        }

    applyToEither 代码示例:

    private static void applyToEither() throws Exception {
        CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f1="+t);
                return t;
            }
        });
        CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f2="+t);
                return t;
            }
        });
        
        CompletableFuture<Integer> result = f1.applyToEither(f2, new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer t) {
                System.out.println(t);
                return t * 2;
            }
        });
    
        System.out.println(result.get());
    }

    acceptEither代码示例:

    private static void acceptEither() throws Exception {
        CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f1="+t);
                return t;
            }
        });
            
        CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f2="+t);
                return t;
            }
        });
        f1.acceptEither(f2, new Consumer<Integer>() {
            @Override
            public void accept(Integer t) {
                System.out.println(t);
            }
        });
    }

    runAfterEither代码示例:

    private static void runAfterEither() throws Exception {
        CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f1="+t);
                return t;
            }
        });
            
        CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f2="+t);
                return t;
            }
        });
        f1.runAfterEither(f2, new Runnable() {
            
            @Override
            public void run() {
                System.out.println("上面有一个已经完成了。");
            }
        });
    }

    runAfterBoth代码示例:

    private static void runAfterBoth() throws Exception {
        CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f1="+t);
                return t;
            }
        });
            
        CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f2="+t);
                return t;
            }
        });
        f1.runAfterBoth(f2, new Runnable() {
            
            @Override
            public void run() {
                System.out.println("上面两个任务都执行完成了。");
            }
        });
    }

    参考文章:

    https://www.jianshu.com/p/6bac52527ca4

    https://www.liaoxuefeng.com/wiki/1252599548343744/1306581182447650

  • 相关阅读:
    P2610 [ZJOI2012]旅游
    P2323 [HNOI2006]公路修建问题
    P3629 [APIO2010]巡逻
    ARC059F
    AGC004D Teleporter
    p3203 弹飞绵羊
    bzoj5450 轰炸
    bzoj4313 三维积木
    cf123E Maze
    bzoj4423 [AMPPZ2013]Bytehattan
  • 原文地址:https://www.cnblogs.com/xiejn/p/14091715.html
Copyright © 2020-2023  润新知