当前位置:   article > 正文

多线程之线程池使用_线程池使用多线程

线程池使用多线程


前言

天下风云出我辈,一入编程岁月催。


一、为什么要使用线程池?

我们使用线程的时候就去创建一个线程,这样实现起来非常简单,但是会有一个问题,如果并发的线程数量很多,并且每一个线程都是执行一个很短的任务就结束了,这样频繁的创建线程就会大大降低系统的效率,因为频繁的创建和销毁都需要时间。这样我们就需要一个可复用就是这个线程执行完成一个任务之后,不会被销毁,继续执行其他的任务。在java中线程池可以达到这样的效果。

二、ThreadPoolExecutor类

比较重要的几个类:

ExecutorService真正的线程池接口。
ScheduledExecutorService能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。
ThreadPoolExecutorExecutorService的默认实现。
ScheduledThreadPoolExecutor继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。

代码如下(示例):

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

设置线程池的参数的方法 :
一种说法,是线程数和cpu数有关系
当应用是IO密集型时,线程数T=2N+1.
当应用是CPU密集型时, 线程数T=N+1
一种说法是,线程池的的设置跟实际的并发量有关系
尽量是两种方法结合起来使用,适合自己业务场景的才是最适合的

corePoolSize - 池中所保存的线程数,包括空闲线程。

maximumPoolSize-池中允许的最大线程数。

keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。

unit - keepAliveTime 参数的时间单位。

workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute方法提交的 Runnable任务。

threadFactory - 执行程序创建新线程时使用的工厂。

handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。

2.线程池执行过程

在这里插入图片描述

三、实际项目中如何使用线程池()

项目需求(示例):用线下的excel新建订单
项目分析:excel量比较大,而且基础数据还要请求基础资料系统,io比较频繁,所以采用了多线程的方式
思路:首先解析excel放入内存,然后拿到这部分数据请求基础资料系统进行拼接形成完整的javabean然后插入数据库

部分代码截取 虽然用到的技术比较老但是也使用了分片的思想,充分利用了线程的资源。注意:invokeAll 可以提交多个任务,在任务完成前该方法会阻塞,直到所有任务完成或中断或超时,返回Future列表。
List<List<DiscountDto>> splitList = ListWrapUtils.split(template, 500);

        List<OrderDetailWrap> orderDetailWraps = Lists.newArrayListWithCapacity(template.size());

        List<TaskWithResult> collect = new ArrayList<>();
        for (int i = 0; i < splitList.size(); i++) {
            collect.add(new TaskWithResult(String.valueOf(i), splitList.get(i)));
        }

        List<Future<Result>> futures = executorService.invokeAll(collect);

        Map<String, Result> resultMap = futures.stream().map(e -> {
            try {
                return e.get();
            } catch (InterruptedException | ExecutionException ex) {
                logger.msg("ioExecutorService执行异常!").exception(ex).error();
            }
            throw new SystemException("ioExecutorService执行异常!");
        }).collect(Collectors.toList()).stream().collect(Collectors.toMap(Result::getId, Function.identity()));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
protected class TaskWithResult implements Callable<Result> {
        /**
         * 数据片id
         */
        private String id;

        private List<? extends AbstTitle> slice;

        public TaskWithResult(String id, List<? extends AbstTitle> slice) {
            this.id = id;
            this.slice = slice;
        }

        @Override
        public Result call() {
            Set<GetSkusByProductCodeAndSizeReqeustVo> request = slice.stream().map(t ->
                    new GetSkusByProductCodeAndSizeReqeustVo(t.getProductCode(), t.getSizeDetailValue()))
                    .collect(Collectors.toSet());
            Optional<List<ProductBaseDto>> response = pdcClientFacade.getSkusByProductCodesAndSize(request);

            return response.map(productBaseDtos -> new Result(id, true, productBaseDtos))
                    .orElseGet(() -> new Result(id, false, Collections.emptyList()));
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

总结

提示:。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/1008785
推荐阅读
相关标签
  

闽ICP备14008679号