多线程线程池详解、 线程异步编排和线程串行化

多线程进阶

文章目录

  • 多线程进阶
  • 前言
  • 一、创建多线程的4种方式(回顾)
    • 1.1、创建线程
    • 1.2、区别
    • 1.3 总结
  • 二、线程池创建和说明
    • 1、自定义线程池
      • 1.1、7大参数说明
      • 1.2、自定义创建
      • 1.3、工作顺序
      • 1.4、案例思考
    • 2、Executors创建功能性线程池
      • 2.1、常见的四种功能性线程池
      • 2.2、创建定长线程池
      • 2.3、为什么使用线程池
  • 三、CompletableFuture异步编排
    • 1.1、CompletableFuture介绍
    • 1.2、常使用的2种创建方式
      • 1.2.1、runAsync没有返回值
      • 1.2.2、supplyAsync有返回值
    • 1.3、 whenComplete 和 handle
      • 1.3.1、 whenComplete + supplyAsync
      • 1.3.2、 handle + supplyAsync(推荐)
  • 四、线程串行化
    • 1、线程串行化的方法
      • 1.1、thenRun (无返回值)
      • 1.2、thenAcceptAsync(获取上个线程的结果,本身无返回值)
      • 1.3、thenAcceptAsync(获取上个线程的结果,自己有返回值)
    • 2、两任务组合 - 都要完成
      • 2.1、runAfterBothAsync(无法感知前面俩个的结果,自己没有返回值)
      • 2.2、runAfterBothAsync(能感知前面的结果,自己没有返回值)
      • 2.3、 thenCombineAsync(能感知前面的结果,自己有返回值)
    • 3、两任务组合 ,任意一个完成。执行任务3
      • 3.1、runAfterEitherAsync
      • 3.2、acceptEitherAsync
      • 3.3、applyToEitherAsync
  • 五、多任务组合(allOf和anyOf)


前言

多线程,可以先看下小编总结的多线程(一)基础篇==>文章入口

一、创建多线程的4种方式(回顾)

1.1、创建线程

  1. 继承 Thread
  2. 实现 Runnable 接口
  3. 实现 Callable 接口 + FutureTask
  4. 线程池一: 自定义方式
  5. 线程池二: Executors的常见4种功能性线程池创建
import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //当前系统中只有一俩个池子。每个异步任务,提交给线程池他自己执行就行
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main...start...");

        //方式1继承Thread  启动线程
        Thread01 thread = new Thread01();
        thread.start();
        System.out.println("============================");

        //方式2实现Runnable接口 启动线程
        Runnable01 runnable01 = new Runnable01();
        new Thread(runnable01).start();
        System.out.println("============================");

        //方式3、实现 Callable 接口 + FutureTask (可以拿到返回结果,可以处理异常) 启动线程
        // 注:FutureTask里面也能放Runnable
        FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
        new Thread(futureTask).start();
        Integer result = futureTask.get();//阻塞等待--等待整个线程执行完成,获取返回结果
        System.out.println("最后的返回结果:" + result);
        System.out.println("============================");

        //方式4 Executors创建线程池执行 Runnable01任务
        execute.execute(new Runnable01());
        System.out.println("main...end...");

    }

    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("继承Thread...运行结果:" + i);
        }
    }

    public static class Runnable01 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("实现Runnable接口...运行结果:" + i);
        }
    }

    public static class Callable01 implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("实现 Callable 接口 + FutureTask...运行结果:" + i);
            return i;
        }
    }

    public static class Runnable04 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("线程池放Runnable04...运行结果:" + i);
        }
    }

}

运行结果:

main...start...
============================
当前线程:12
继承Thread...运行结果:5
============================
当前线程:13
实现Runnable接口...运行结果:5
当前线程:14
实现 Callable 接口 + FutureTask...运行结果:5
最后的返回结果:5
============================
main...end...
当前线程:15
实现Runnable接口...运行结果:5

1.2、区别

方式1、2 不能得到返回值。3可以获取返回值
方式1、2、3 都不能控制资源
方式4 可以控制资源,性能稳定。

1.3 总结

在业务场景,以上3种方式启动线程都不使用。会导致资源耗尽。

将所有多线程异步任务都交给线程池执行

二、线程池创建和说明

1、自定义线程池

1.1、7大参数说明

  1. int corePoolSize:核心线程数
  2. int maximumPoolSize:最大线程数量。控制资源
  3. long keepAliveTime: 存活时间
  4. TimeUnit unit: 时间单位
  5. BlockingQueue workQueue: 阻塞队列。
  6. ThreadFactory threadFactory: 线程的创建工厂
  7. RejectedExecutionHandler handler: 拒绝策略
线程池的7大参数:
     01int corePoolSize: 核心线程数(一直存在,除非allowCoreThreadTimeOut)。
           线程池,创建好以后就准备就绪的线程数量,就等待接收异步任务来执行
           例如:corePoolSize:[5]  等于 5Thread thread = new Thread()
       
     02int maximumPoolSize: 最大线程数量。控制资源
         
     03long keepAliveTime: 存活时间。如果当前的线程数量大于核心数量(corePoolSize)
           释放空闲的线程(maximumPoolSize - corePoolSize)。
           只要线程空闲大于指定的keepAliveTime,就会释放
         
     04TimeUnit unit: 时间单位
         
     05BlockingQueue<Runnable> workQueue: 阻塞队列。
            如果任务有很多,就会将目前多的任务放在队列里面
            只要有线程空闲,就会去队列里面取出新的任务执行
         
     06ThreadFactory threadFactory: 线程的创建工厂
         
     07RejectedExecutionHandler handler: 拒绝策略
           如果队列满了,按照我们指定的拒绝策略拒绝执行任务
          

1.2、自定义创建

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {


    public static void main(String[] args) throws Exception {
      /**
        *   new LinkedBlockingDeque<>():默认是Integer的最大值。容易导致内存不够。
        *   要指定数量,例如: new LinkedBlockingDeque<>(10000)
        */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        executor.execute(new Runnable05());
    }

    public static class Runnable05 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("线程池放Runnable05...运行结果:" + i);
        }
    }
}

运行结果:
多线程线程池详解、 线程异步编排和线程串行化_第1张图片

1.3、工作顺序

  1. 线程池创建,准备好 core 数量的核心线程,准备接受任务
  2. core 满了,就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队列获取任务执行
  3. 阻塞队列满了,就直接开新线程执行,最大只能开到 max 指定的数量
  4. max 满了,就会使用 RejectedExecutionHandler handler 指定的拒绝策略进行处理
  5. max都执行完了,有很多空闲。在执行的时间keepAliveTime以后,释放Max-core这些线程。最终保持到 core 大小
  6. 所有的线程创建都是由指定的 factory 创建的。

1.4、案例思考

一个线程池 core 7; max 20 ,queue:50,100 并发进来怎么分配的?

先有 7 个能直接得到执行,接下来 50 个进入队列排队,在多开 13 个继续执行。
现在 70 个被安排上了。剩下 30 个默认拒绝策略


如果不想抛弃还要执行。使用CallerRunsPolicy策略。会同步执行
或者将最老的,一直不执行的丢弃

2、Executors创建功能性线程池

2.1、常见的四种功能性线程池

  1. Executors.newCachedThreadPool() 可缓存线程池(core是0,所有都可以回收)
  2. Executors.newFixedThreadPool() 固定大小的线程池(core=max,都不可以回收)
  3. Executors.newScheduledThreadPool() 定时任务的线程池
  4. Executors.newSingleThreadExecutor() 单线程的线程池,后台从队列里面一个一个拿出来执行

单线程的线程池应用说明:
应用场景:分布式的情况下,保证双写一致的情况,需要将同样的业务留给同一台服务器或者线程来执行处理

2.2、创建定长线程池

  //大小为10
  ExecutorService execute = Executors.newFixedThreadPool(10);
  //执行
  execute.execute(new Runnable01());//看创建多线程的4种方式(回顾)里面的第4种

2.3、为什么使用线程池

  1. 降低资源的消耗==>通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗
  2. 提高响应速度==>因为线程池中的线程数没有超过线程池的最大上限时,有的线程处于等待分配任务的状态,当任务来时无需创建新的线程就能执行
  3. 提高线程的可管理性==>线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销。无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,使用线程池进行统一分配

三、CompletableFuture异步编排

1.1、CompletableFuture介绍

在 Java 8 中, 新增加了一个包含 50 个方法左右的类: CompletableFuture,提供了非常强大的
Future 的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以
通过回调的方式处理计算结果,并且提供了转换和组合 CompletableFuture 的方法。

1.2、常使用的2种创建方式

  1. CompletableFuture.runAsync
  2. CompletableFuture.supplyAsync
  3. 说明:xxxAsync表示异步,没有Async表示同步

1.2.1、runAsync没有返回值

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        //可以传入自定义的线程池,否则就用默认的线程池;
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("main...start...");
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
        }, execute);
        System.out.println("main...end...");
    }
}

效果:
多线程线程池详解、 线程异步编排和线程串行化_第2张图片

1.2.2、supplyAsync有返回值

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("main...start...");
        //可以传入自定义的线程池,否则就用默认的线程池;
        //第二种:supplyAsync的whenComplete
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, execute);
        Integer res = future.get();
        System.out.println("返回值:"+res);

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

}

运行结果:
多线程线程池详解、 线程异步编排和线程串行化_第3张图片

1.3、 whenComplete 和 handle

  1. 方法执行完成后的感知==>whenComplete
  2. 方法执行完成后的处理==>handle

1.3.1、 whenComplete + supplyAsync

只能感知异常,无法修改返回的数据

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("main...start...");
                CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
//            int i = 10 / 0;//制造异常
            System.out.println("运行结果:" + i);
            return i;
        }, execute).whenComplete((result,exception)->{
            //【whenComplete缺点只能感知】
            //感知异常,但是没法修改返回数据
            System.out.println("异步任务执行完成了。。。结果是:"+result+" "+"异常是:"+exception);
        }).exceptionally(throwable -> {
            //可以感知异常,同事返回默认值
            return 10;//出现异常返回10
        });

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

}

结果:
多线程线程池详解、 线程异步编排和线程串行化_第4张图片

1.3.2、 handle + supplyAsync(推荐)

处理完在返回

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("main...start...");
        //第二种:supplyAsync的handle
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, execute).handle((result, exception) -> {
            if (result != null) {
                return result * 50;
            }
            if (exception != null) {
                return 0;
            }
            return 0;
        });
        Integer returnResult = future.get();
        System.out.println("返回的结果:"+returnResult);

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

}

运行结果:
多线程线程池详解、 线程异步编排和线程串行化_第5张图片

四、线程串行化

  1. thenRun 不能获取到上一步的执行结果,无返回值
  2. thenAcceptAsync 能接收上一步结果,但是无返回值
  3. thenApplyAsync 能接收上一步结果,有返回值
thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值

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

thenRun 方法:只要上面的任务执行完成,就开始执行 thenRun,只是处理完任务后,执行thenRun 的后续操作带有 Async 默认是异步执行的。 同之前。以上都要前置任务成功完成。

1、线程串行化的方法

1.1、thenRun (无返回值)

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("===========main...start...===============");

        //thenRunAsync
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, execute).thenRunAsync(() -> {
            //模拟第二个线程任务
            System.out.println("任务2启动了。。。模拟第二个线程任务");
        }, execute);
        
        System.out.println("============main...start...===============");
    }

}

1.2、thenAcceptAsync(获取上个线程的结果,本身无返回值)

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("===========main...start...===============");

        //thenAcceptAsync
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, execute).thenAcceptAsync(result -> {
            //模拟第二个线程任务,拿到上一个线程的处理结果,继续线程操作
            System.out.println("任务2启动了《模拟第二个线程任务,拿到上一个线程的处理结果,继续线程操作》..上一次的结果:" + result);
        }, execute);

        System.out.println("============main...start...===============");
    }

}

1.3、thenAcceptAsync(获取上个线程的结果,自己有返回值)

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("===========main...start...===============");

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1=运行结果:" + i);
            return i;
        }, execute).thenApplyAsync((result) -> {
            System.out.println("任务2启动了《模拟第二个线程任务,拿到上一个线程的处理结果,继续线程操作》..上一次的结果:" + result);
            return "Hello " + result;
        }, execute);
        String s = future.get();
        System.out.println("有返回值!!!==>最后的返回值:"+s);

        System.out.println("============main...start...===============");
    }

}

效果:
多线程线程池详解、 线程异步编排和线程串行化_第6张图片

2、两任务组合 - 都要完成

  • thenCombine:组合两个 future,获取两个 future 的返回结果,并返回当前任务的返回值
  • thenAcceptBoth:组合两个 future,获取两个 future 任务的返回结果,然后处理任务,没有返回值。
  • runAfterBoth:组合两个 future,不需要获取 future 的结果,只需两个 future 处理完任务后,
    处理该任务

2.1、runAfterBothAsync(无法感知前面俩个的结果,自己没有返回值)

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("===========main...start...===============");

        /**
         * 俩个都完成
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("任务1结束");
            return i;
        }, execute);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, execute);

        //第一种 runAfterBothAsync无法感知前面俩个的结果
        future01.runAfterBothAsync(future02,()->{
            //线程1组合线程2,都完成以后开始任务3
            System.out.println("任务3开始");
        },execute);

//        //第二种 thenAcceptBothAsync能感知前面的结果
//        future01.thenAcceptBothAsync(future02,(f1,f2)->{
//            System.out.println("任务3开始");
//            System.out.println("任务1的返回值:"+f1);
//            System.out.println("任务2的返回值:"+f2);
//        },execute);


//        //第三种 thenCombineAsync能感知前面的结果,自己有返回值
//        CompletableFuture future03 = future01.thenCombineAsync(future02, (f1, f2) -> {
//            System.out.println("任务3开始");
//            return f1 + ":" + f2 + "我是任务3的返回";
//        }, execute);
//        String s = future03.get();
//        System.out.println(s);


        System.out.println("============main...start...===============");
    }

}

效果:
多线程线程池详解、 线程异步编排和线程串行化_第7张图片

2.2、runAfterBothAsync(能感知前面的结果,自己没有返回值)


import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("===========main...start...===============");

        /**
         * 俩个都完成
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("任务1结束");
            return i;
        }, execute);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, execute);

//        //第一种 runAfterBothAsync无法感知前面俩个的结果
//        future01.runAfterBothAsync(future02,()->{
//            //线程1组合线程2,都完成以后开始任务3
//            System.out.println("任务3开始");
//        },execute);

        //第二种 thenAcceptBothAsync能感知前面的结果
        future01.thenAcceptBothAsync(future02,(f1,f2)->{
            System.out.println("任务3开始");
            System.out.println("任务1的返回值:"+f1);
            System.out.println("任务2的返回值:"+f2);
        },execute);

//        //第三种 thenCombineAsync能感知前面的结果,自己有返回值
//        CompletableFuture future03 = future01.thenCombineAsync(future02, (f1, f2) -> {
//            System.out.println("任务3开始");
//            return f1 + ":" + f2 + "我是任务3的返回";
//        }, execute);
//        String s = future03.get();
//        System.out.println(s);


        System.out.println("============main...start...===============");
    }

}

效果:
多线程线程池详解、 线程异步编排和线程串行化_第8张图片

2.3、 thenCombineAsync(能感知前面的结果,自己有返回值)

package com.atguigu.gulimall.product;

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("===========main...start...===============");

        /**
         * 俩个都完成
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("任务1结束");
            return i;
        }, execute);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, execute);

//        //第一种 runAfterBothAsync无法感知前面俩个的结果
//        future01.runAfterBothAsync(future02,()->{
//            //线程1组合线程2,都完成以后开始任务3
//            System.out.println("任务3开始");
//        },execute);

//        //第二种 thenAcceptBothAsync能感知前面的结果
//        future01.thenAcceptBothAsync(future02,(f1,f2)->{
//            System.out.println("任务3开始");
//            System.out.println("任务1的返回值:"+f1);
//            System.out.println("任务2的返回值:"+f2);
//        },execute);

        //第三种 thenCombineAsync能感知前面的结果,自己有返回值
        CompletableFuture<String> future03 = future01.thenCombineAsync(future02, (f1, f2) -> {
            System.out.println("任务3开始");
            return f1 + ":" + f2 + "我是任务3的返回";
        }, execute);
        String s = future03.get();
        System.out.println(s);


        System.out.println("============main...start...===============");
    }

}

效果:
多线程线程池详解、 线程异步编排和线程串行化_第9张图片

3、两任务组合 ,任意一个完成。执行任务3

俩个任务,只要有一个完成,就执行任务3

  1. runAfterEitherAsync:不感知结果,自己也无返回值
  2. acceptEitherAsync:感知结果,自己无返回值[注:任务1和任务2的返回值类型必须一致]
  3. applyToEitherAsync: 感知结果,自己有返回值

3.1、runAfterEitherAsync

package com.atguigu.gulimall.product;

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("===========main...start...===============");

        /**
         * 来个任务,任意一个完成
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("任务1结束");
            return i;
        }, execute);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, execute);

        //第一种 runAfterEitherAsync
        future01.runAfterEitherAsync(future02,()->{
            System.out.println("任务3开始");
        },execute);

//        //第二种 acceptEitherAsync==>[任务1和任务2的返回值类型必须一致]
//        future01.acceptEitherAsync(future02,(res)->{
//            System.out.println("任务3开始..."+"之前的线程1的结果:"+res);
//        },execute);
//
//        //第三种 applyToEitherAsync
//        CompletableFuture future03 = future01.applyToEitherAsync(future02, (res) -> {
//            System.out.println("任务3开始..." + "之前的线程1的结果:" + res);
//            return res.toString() + "-->hello";
//        }, execute);
//        String f3 = future03.get();
//        System.out.println("f3:"+f3);

        System.out.println("============main...start...===============");
    }

}

效果:
多线程线程池详解、 线程异步编排和线程串行化_第10张图片

3.2、acceptEitherAsync

package com.atguigu.gulimall.product;

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("===========main...start...===============");

        /**
         * 来个任务,任意一个完成
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("任务1结束");
            return i;
        }, execute);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, execute);

//        //第一种 runAfterEitherAsync
//        future01.runAfterEitherAsync(future02,()->{
//            System.out.println("任务3开始");
//        },execute);

        //第二种 acceptEitherAsync==>[任务1和任务2的返回值类型必须一致]
        future01.acceptEitherAsync(future02,(res)->{
            System.out.println("任务3开始..."+"之前的线程1的结果:"+res);
        },execute);

//        //第三种 applyToEitherAsync
//        CompletableFuture future03 = future01.applyToEitherAsync(future02, (res) -> {
//            System.out.println("任务3开始..." + "之前的线程1的结果:" + res);
//            return res.toString() + "-->hello";
//        }, execute);
//        String f3 = future03.get();
//        System.out.println("f3:"+f3);

        System.out.println("============main...start...===============");
    }

}

效果:
多线程线程池详解、 线程异步编排和线程串行化_第11张图片

3.3、applyToEitherAsync

package com.atguigu.gulimall.product;

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("===========main...start...===============");

        /**
         * 来个任务,任意一个完成
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("任务1结束");
            return i;
        }, execute);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, execute);

//        //第一种 runAfterEitherAsync
//        future01.runAfterEitherAsync(future02,()->{
//            System.out.println("任务3开始");
//        },execute);

//        //第二种 acceptEitherAsync==>[任务1和任务2的返回值类型必须一致]
//        future01.acceptEitherAsync(future02,(res)->{
//            System.out.println("任务3开始..."+"之前的线程1的结果:"+res);
//        },execute);

//        //第三种 applyToEitherAsync
        CompletableFuture<String> future03 = future01.applyToEitherAsync(future02, (res) -> {
            System.out.println("任务3开始..." + "之前的线程1的结果:" + res);
            return res.toString() + "-->hello";
        }, execute);
        String f3 = future03.get();
        System.out.println("f3:"+f3);

        System.out.println("============main...start...===============");
    }

}

效果:
多线程线程池详解、 线程异步编排和线程串行化_第12张图片

五、多任务组合(allOf和anyOf)

  1. allOf:等待所有任务完成
  2. anyOf:只要有一个任务完成
  3. 注:anyOf就是有一个完成就可以返回。
package com.atguigu.gulimall.product;

import java.util.concurrent.*;

/**
 * @author suqinyi
 * @Date 2021/8/22
 */
public class Thread4Test {

    //自定义的线程池
    public static ExecutorService execute = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        System.out.println("===========main...start...===============");

        /**
         * 多任务组合
         */
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("查询物品的图片信息1");
            return "hello.jpg";
        },execute);
        
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("查询物品的属性2");
            return "蓝色+256G";
        },execute);
        
        CompletableFuture<String> futureDesc= CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("查询物品的介绍3");
            return "介绍=价格998";
        },execute);

        //1、allOf
        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
        //allOf.join();//插队---get或者join都行
        allOf.get();//等待所有结果完成--->最后的一句话最后打印.阻塞住==>就是这个 System.out.println("============main...start...===============");
        System.out.println("futureImg:"+futureImg.get()+"..."+"futureAttr:"+futureAttr.get()+"..."+"futureDesc:"+futureDesc.get());

//        //2、anyOf
//        CompletableFuture anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);
//        Object o = anyOf.get();
//        System.out.println("anyOf:"+o);


        System.out.println("============main...start...===============");
    }

}

 
  

allOf的效果:
多线程线程池详解、 线程异步编排和线程串行化_第13张图片
anyOf的效果:
多线程线程池详解、 线程异步编排和线程串行化_第14张图片
上一篇:java基础总结之多线程(一)

你可能感兴趣的:(多线程,线程池,多线程,串行化,多线程异步编排,Java基础)