Java线程池原理以及如何使用Guava优化接口的响应速度

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

线程池原理图
在这里插入图片描述
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);
    }
}






  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
优化Java接口响应速度,可以尝试以下几个方法: 1. 使用缓存:对于一些计算耗时较长但结果不经常变动的接口,可以将结果缓存起来,在下次请求时直接返回缓存的结果,避免重复计算。可以使用内存缓存(如Ehcache、Guava Cache)或者分布式缓存(如Redis、Memcached)来实现。 2. 异步处理:对于一些耗时的操作,可以将其放入消息队列中异步处理,这样可以立即返回响应给客户端,而不是等待操作完成。常见的消息队列有Kafka、RabbitMQ等。 3. 使用连接池:对于与其他服务进行通信的接口,如数据库连接、HTTP请求等,使用连接池可以避免频繁地创建和销毁连接,提高性能和响应速度。常见的连接池有HikariCP、Apache Commons Pool等。 4. 数据库优化:如果接口需要大量读取数据库数据,可以优化数据库查询语句、创建索引、拆分表等方式来提高查询性能。 5. 避免阻塞操作:在接口的实现中,尽量避免阻塞操作,如IO操作、网络请求等,可以使用非阻塞IO、多线程等方式来提高并发性能。 6. 代码优化:对接口的实现代码进行优化,如减少不必要的循环和判断、使用高效的数据结构和算法等,可以提高代码执行效率。 以上是一些常见的方法,具体的优化策略需要根据具体的应用场景和需求来确定。在实际应用中,可以通过性能测试和监控工具来评估接口的性能,并对瓶颈进行针对性优化

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值