为什么不适用new Thread创建线程?
①线程多了不一定快 ------ 线程是CPU(或操作系统)的一个资源,如果手动去创建一个线程,例如一个高并发项目十万人访问,每个用户创建一个线程,对于操作系统来说就会创建很多线程,这些线程就会抢夺CPU资源,造成线程调度频繁
②容易出现OOM ------ 来了多少请求就创建多少线程
线程池原理:当主线程调用execute方法或submit方法提交任务到线程池里面的时候,有空闲核心线程就交给核心线程去处理,核心线程用完,先进入阻塞队列(先进先出的队列),此时任务没有被执行,核心线程如果空闲就会读取阻塞队列的任务去执行。如果阻塞队列满了,主线程继续提交任务,就会判断当前线程池的容量是否达到了最大线程,如果没有达到最大线程,就会创建新的线程去执行阻塞队列的任务或用户提交的任务。如果达到最大线程就会执行拒绝策略。
核心线程的特点:①没有任务的时候,核心线程可以全部创建好
②没有任务的时候,核心线程不可以回收
拒绝策略:
①饱和策略(AbortPolicy) 这个线程池到达饱和状态以后,直接把主线程提交的任务抛个异常出来,告诉主线程当前线程池已经饱和了
②调用者运行(CallerRunsPolicy) 有一些交易订单请求不能直接抛掉,比如请求中带有金额,线程池会把不能执行的任务再放回到主线程,让主线程执行,主线程就会变成一个串行过程。
Java有多少中线程池?
Java里面只有一种线程池ThreadPoolExecutor

线程池原理图

java接口吞吐量斷崖式下降_多线程


Guava对Java线程的改进

① Guava为Java并行编程Future提供了很多有用扩展,其主要接口为ListenableFuture,并借助于Futures静态扩展。

②继承自Future的ListenableFuture,允许我们添加回调函数,在线程运算完成时执行回调函数。

③如果Future带有回调,这样是不是可以避免我们直接操作get()获取返回值。

1.JDK线程池使用

@RestController
public class JdkThreadController {

    @Resource
    private OuterService outerService;

    @RequestMapping("/test/jdk")
    public Map<String, Object> execute() throws ExecutionException, InterruptedException {
        // 固定大小的线程池 核心线程数和最大线程数=10
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        // 记录开始时间
        Long start = System.currentTimeMillis();
        // 异步调用用户服务
        Future<Long> userServiceFuture = executorService.submit(new Callable<Long>() {
            @Override
            public Long call() throws Exception {
                return outerService.userService();
            }
        });
        // 异步调用订单服务
        Future<Long> orderServiceFuture = executorService.submit(new Callable<Long>() {
            @Override
            public Long call() throws Exception {
                return outerService.orderService();
            }
        });
        // 异步调用商品服务
        Future<Long> itemServiceFuture = executorService.submit(new Callable<Long>() {
            @Override
            public Long call() throws Exception {
                return outerService.itemService();
            }
        });
        // 阻塞 等待执行结果
        long userServiceResult = userServiceFuture.get();
        long orderServiceResult = orderServiceFuture.get();
        long itemServiceResult = itemServiceFuture.get();

        //结束调用的时间
        long end = System.currentTimeMillis();
        //计算结果
        long result = userServiceResult + orderServiceResult + itemServiceResult;
        String time = "总调用时间是:" + (end - start) + "毫秒";
        //为什么要初始化4个容量的Map
        Map<String, Object> resultMap = new HashMap<>(4);
        resultMap.put("time", time);
        resultMap.put("result", result);
        //结果
        return resultMap;
    }
}
@Service
public class OuterService {
    /**
     * 用户服务
     */
    public long userService() {
        System.out.println("用户服务开始执行");
        try {
            //模拟耗时1000ms的用户服务
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("用户服务执行结束");
        //假设用户服务返回值=1
        return 1;
    }

    /**
     * 订单服务
     */
    public long orderService() {
        System.out.println("订单服务开始执行");
        try {
            //模拟耗时2000ms的订单服务
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("订单服务执行结束");
        //假设订单服务返回值=3
        return 3;
    }

    /**
     * 商品服务
     */
    public long itemService() {
        System.out.println("商品服务开始执行");
        try {
            //模拟耗时3000ms的商品服务
            Thread.sleep(3000);
            //模拟调用超时或者服务异常
            // throw new RuntimeException("Oh My God, OrderService Exception!!!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("商品服务执行结束");
        //假设商品服务返回值=5
        return 5;
    }

    /**
     * 地址服务
     */
    public long addressService() {
        System.out.println("地址服务开始执行");
        try {
            //模拟耗时5000ms的地址服务
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("地址服务执行结束");
        //假设地址服务返回值=7
        return 7;
    }
}

2.guava线程池使用

/**

  • 2.1公用的线程池
    */
@Component
public class ListeningExecutors {
    @Bean
    public ListeningExecutorService createListeningExecutorService(){
        //创建线程池
        return MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
    }
}
public class FutureCallBackTask implements FutureCallback<Object> {

    /**
     * 成功的回调
     * @param result
     */
    @Override
    public void onSuccess(Object result) {
        //执行回调函数
        System.out.println("进入正确的回调函数");
        //得到任务执行的结果
        System.out.printf("任务执行的结果是:%s%n", result);
    }

    /**
     * 失败的回调
     * @param thrown
     */
    @Override
    public void onFailure(Throwable thrown) {
        System.out.println("进入错误的回调函数");
        System.out.printf("系统出错了,错误原因是:%s%n", thrown.getMessage());
    }
}
@RestController
public class GuavaThreadController {
    @Autowired
    private ListeningExecutorService listeningExecutorService;
    @RequestMapping("/test/guava")
    public void execute(){
        //一个耗时的任务
        ListenableFuture<Boolean> listenableFuture = listeningExecutorService.submit(() -> {
            Thread.sleep(5000);
            return true;
        });
        //注册回调事件
        Futures.addCallback(listenableFuture,new FutureCallBackTask(),listeningExecutorService);
    }
}

另一种优化方案,不改动公司内部的线程池

@Component
public class ListeningExecutors {

    @Bean
    public ListeningExecutorService createListeningExecutorService() {
        // 创建线程池
        return MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
    }
}
public class FutureCallBackTask implements FutureCallback<Object> {

    /**
     * 成功的回调
     * @param result
     */
    @Override
    public void onSuccess(Object result) {
        //执行回调函数
        System.out.println("进入正确的回调函数");
        //得到任务执行的结果
        System.out.printf("任务执行的结果是:%s%n", result);
    }

    /**
     * 失败的回调
     * @param thrown
     */
    @Override
    public void onFailure(Throwable thrown) {
        System.out.println("进入错误的回调函数");
        System.out.printf("系统出错了,错误原因是:%s%n", thrown.getMessage());
    }
}
@RestController
public class JdkFutureAdaptersController {
    @Autowired
    private ListeningExecutorService listeningExecutorService;
    @RequestMapping("/test/adapter")
    public void execute(){
      // 记录开始时间
        Long start = System.currentTimeMillis();
        // 一个耗时的任务
        Future<Boolean> future = listeningExecutorService.submit(new Callable<Boolean>() {
            /**
             * Computes a result, or throws an exception if unable to do so.
             *
             * @return computed result
             * @throws Exception if unable to compute a result
             */
            @Override
            public Boolean call() throws Exception {
                //模拟耗时5s
                Thread.sleep(5000);
                return true;
            }
        });
        ListenableFuture<Boolean> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
        Futures.addCallback(listenableFuture,new FutureCallBackTask(),listeningExecutorService);
    }
}

最后,guava的高级特性使用

@Component
public class ListeningExecutors {

    @Bean
    public ListeningExecutorService createListeningExecutorService() {
        // 创建线程池
        return MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
    }
}
@Service
public class OuterService {
    /**
     * 用户服务
     */
    public long userService() {
        System.out.println("用户服务开始执行");
        try {
            //模拟耗时1000ms的用户服务
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("用户服务执行结束");
        //假设用户服务返回值=1
        return 1;
    }

    /**
     * 订单服务
     */
    public long orderService() {
        System.out.println("订单服务开始执行");
        try {
            //模拟耗时2000ms的订单服务
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("订单服务执行结束");
        //假设订单服务返回值=3
        return 3;
    }

    /**
     * 商品服务
     */
    public long itemService() {
        System.out.println("商品服务开始执行");
        try {
            //模拟耗时3000ms的商品服务
            Thread.sleep(3000);
            //模拟调用超时或者服务异常
            // throw new RuntimeException("Oh My God, OrderService Exception!!!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("商品服务执行结束");
        //假设商品服务返回值=5
        return 5;
    }

    /**
     * 地址服务
     */
    public long addressService() {
        System.out.println("地址服务开始执行");
        try {
            //模拟耗时5000ms的地址服务
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("地址服务执行结束");
        //假设地址服务返回值=7
        return 7;
    }
}
/**
 * @Description: 高级特性介绍
 * <p>
 * transform:对于ListenableFuture的返回值进行转换。
 * <p>
 * allAsList:对多个ListenableFuture的合并,返回一个当所有Future成功时返回多个Future返回值组成的List对象。
 * 注:当其中一个Future失败或者取消的时候,将会进入失败或者取消。
 * <p>
 * successfulAsList:和allAsList相似,唯一差别是对于失败或取消的Future返回值用null代替。不会进入失败或者取消流程。
 * <p>
 * immediateFuture/immediateCancelledFuture: 立即返回一个待返回值的ListenableFuture。
 * <p>
 * makeChecked: 将ListenableFuture 转换成CheckedFuture。CheckedFuture 是一个ListenableFuture 。
 * 其中包含了多个版本的get 方法,方法声明抛出检查异常.这样使得创建一个在执行逻辑中可以抛出异常的Future更加容易
 * <p>
 * JdkFutureAdapters.listenInPoolThread(jdkthread): guava同时提供了将JDK Future转换为ListenableFuture的接口函数。
 */
@RestController
public class SeniorListenableFutureController {

    @Autowired
    private ListeningExecutorService listeningExecutorService;
    @Autowired
    private OuterService outerService;

    @RequestMapping("/test/senior")
    public Map<String, Object> execute() throws ExecutionException, InterruptedException {

        long start = System.currentTimeMillis();

        // 异步调用用户服务
        ListenableFuture<Long> userServiceFuture = listeningExecutorService.submit(new Callable<Long>() {
            @Override
            public Long call() throws Exception {
                return outerService.userService();
            }
        });

        // 异步调用订单服务
        ListenableFuture<Long> orderServiceFuture = listeningExecutorService.submit(new Callable<Long>() {
            @Override
            public Long call() throws Exception {
                return outerService.orderService();
            }
        });

        // 异步调用商品服务
        ListenableFuture<Long> itemServiceFuture = listeningExecutorService.submit(new Callable<Long>() {
            @Override
            public Long call() throws Exception {
                return outerService.itemService();
            }
        });
        //注册商品服务回调
        addCallBack(itemServiceFuture);

        // .......
        // 对多个ListenableFuture的合并,返回一个当所有Future成功时返回多个Future返回值组成的List对象。
        // 注:当其中一个Future失败或者取消的时候,会怎样?
          //拿到三个任务的成功执行结果
        final ListenableFuture<List<Long>> threeServicesFutures = Futures.successfulAsList(userServiceFuture, orderServiceFuture, itemServiceFuture);

        //对于多个ListenableFuture的进行转换,返回一个新的ListenableFuture
        final ListenableFuture<Long> transform = Futures.transformAsync(threeServicesFutures, new AsyncFunction<List<Long>, Long>() {
            /**
             * 用给定的输入封装一个特定的ListenableFuture作为输出
             *
             * @param input 输入的ListenableFuture对象
             */
            @Override
            public ListenableFuture<Long> apply(@Nullable List<Long> input) {

                if (input == null || input.isEmpty()) {
                    return null;
                }
                // 这里可以对input进行复杂的处理,返回最终的一个结果
                // 比如:对用户服务,订单服务,商品服务的远程调用结果进行封装
                long result = 0;
                for (Long serviceResult : input) {
                    if (serviceResult != null) {
                        result += serviceResult;
                    }
                }
                // 立即返回一个带返回值的ListenableFuture
                return Futures.immediateFuture(result);
            }
        }, listeningExecutorService);

        // 异步调用地址服务
        ListenableFuture<Long> addressServiceFuture = listeningExecutorService.submit(new Callable<Long>() {
            @Override
            public Long call() throws Exception {
                return outerService.addressService();
            }
        });

        final ListenableFuture<List<Long>> finalFutures = Futures.successfulAsList(transform, addressServiceFuture);

        ListenableFuture<Long> finalResult = Futures.transformAsync(finalFutures, new AsyncFunction<List<Long>, Long>() {
            @Override
            public ListenableFuture<Long> apply(@Nullable List<Long> input) throws Exception {
                if (CollectionUtils.isEmpty(input)) {
                    return null;
                }
                // 这里可以对input进行复杂的处理,返回最终的一个结果
                long result = 0;
                // 比如:对上面的用户服务,订单服务,商品服务的总结果和地址服务再封装
                for (Long serviceResult : input) {
                    if (serviceResult != null) {
                        result += serviceResult;
                    }
                }
                // 立即返回一个带返回值的ListenableFuture
                return Futures.immediateFuture(result);
            }
        }, listeningExecutorService);

        // 注册回调事件
        addCallBack(finalResult);
        long end = System.currentTimeMillis();
        String time = "总调用时间是:" + (end - start) + "毫秒";
        //为什么要初始化4个容量的Map
        Map<String, Object> resultMap = new HashMap<>(3);
        resultMap.put("time", time);
        //结果
        return resultMap;
    }

    /**
     * 添加回调
     * @param listenableFuture
     */
    private void addCallBack(ListenableFuture<Long> listenableFuture) {
        Futures.addCallback(listenableFuture, new FutureCallback<Long>() {
            @Override
            public void onSuccess(@Nullable Long result) {
                System.out.printf("服务调用成功,执行结果是%s%n",result);
            }

            @Override
            public void onFailure(Throwable t) {
                System.out.printf("服务调用异常%s%n", t);
            }
        }, listeningExecutorService);
    }
}