IDEA 导入阿里规约插件, 当你这样写代码时, 插件就会自动监测出来, 并给你红线提醒.
告诉你手动创建线程池, 效果会更好.
在探秘原因之前我们要先了解一下线程池 ThreadPoolExecutor 都有哪些参数及其意义.
ThreadPoolExecutor 构造方法:
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue<Runnable> workQueue,
- ThreadFactory threadFactory,
- RejectedExecutionHandler handler) {
- //code...
- }
参数的意义:
1.corePoolSize 指定了线程池里的线程数量, 核心线程池大小
2.maximumPoolSize 指定了线程池里的最大线程数量
3.keepAliveTime 当线程池线程数量大于 corePoolSize 时候, 多出来的空闲线程, 多长时间会被销毁.
4.unit 时间单位
5.workQueue 任务队列, 用于存放提交但是尚未被执行的任务.
6.threadFactory 线程工厂, 用于创建线程, 一般可以用默认的
7.handler 拒绝策略, 当任务过多时候, 如何拒绝任务. 当提交任务数超过 maximumPoolSize + workQueue 的 size 之和, 任务交给 RejectedExecutionHandler 处理
阿里规约之所以强制要求手动创建线程池, 也是和这些参数有关. 具体为什么不允许, 规约是这么说的:
线程池不允许使用 Executors 去创建, 而是通过 ThreadPoolExecutor 的方式, 这样的处理方式让写的同学更加明确线程池的运行规则, 规避资源耗尽的风险.
说明: Executors 各个方法的弊端:
1)newFixedThreadPool 和 newSingleThreadExecutor:
主要问题是堆积的请求处理队列可能会耗费非常大的内存, 甚至 OOM.
2)newCachedThreadPool 和 newScheduledThreadPool:
主要问题是线程数最大数是 Integer.MAX_VALUE, 可能会创建数量非常多的线程, 甚至 OOM.
看一下这两种弊端怎么导致的.
第一种是因为, 创建了一个 size 为 Integer.MAX_VALUE 的线程阻塞队列, 可能会堆积大量的请求, 消耗很大的内存, 甚至导致 OOM.
第二种是因为, 创建了的线程池允许的最大线程数是 Integer.MAX_VALUE, 可能会创建大量的线程, 消耗资源, 甚至导致 OOM.
这两种都是有点极端的, 稍微点进去看一下源码就能看出来.
阿里规约提倡手动创建线程池, 而非 Java 内置的线程池, 给出的正例如下:
正例 1:
- //org.apache.commons.lang3.concurrent.BasicThreadFactory
- ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
- new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
正例 2:
- ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
- //Common Thread Pool
- ExecutorService pool = new ThreadPoolExecutor(5, 200,
- 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
- pool.execute(()-> System.out.println(Thread.currentThread().getName()));
- pool.shutdown();//gracefully shutdown
正例 3:
- <bean id="userThreadPool"
- class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
- <property name="corePoolSize" value="10" />
- <property name="maxPoolSize" value="100" />
- <property name="queueCapacity" value="2000" />
- <property name="threadFactory" value= threadFactory />
- <property name="rejectedExecutionHandler">
- <ref local="rejectedExecutionHandler" />
- </property>
- </bean>
- //in code
- userThreadPool.execute(thread);
---
关注公众号, 编程大道, 回复 "手册" 获取阿里 Java 开发手册最新版.
来源: https://www.cnblogs.com/ibigboy/p/11298004.html