因为快到年后了,所以过我年过来可能要跳槽,所以这段时间一直在复习一下知识,然后就想着做下笔记记录一下,上一篇文章说了线程池的创建方式以及线程池的7大参数是什么,有什么用,今天我们来手写一下线程池,以及线程池的拒绝策略各个都代表着啥意思,我们应该这么去根据自己的业务去选择
在实际生产中我们会使用那种方式去进行创建线程?
这个问题可能会被问到,因为我们之前说了线程池有3种创建方式那么我们在生产环境中,应该选择哪一种进行创建线程池?,答案是都不使用,因为问题就在于阻塞队列哪里,我们来看看源码
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
/**
* Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}.
*/
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
也就是这个初始化值太大了,在生产环境中我们如果使用默认的创建方式有可能会出OOM的问题产生,所以一般都是要我们来手动的创建线程池也就是创建这个 类 ThreadPoolExecutor
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2,5,1L,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
好了,从这里来我们就可以看出,只要我们知道了线程池的参数那么这个代码就很容易看懂了,这里我就不在说了,主要是看看线程池的拒绝策略,这里我使用了是默认的策略,就是说,当线程请求数大于max和阻塞队列的值时就抛出异常
我们max最大连接数是5,阻塞队列最大是8,所以我们也就只能同时处理8个请求,多了就会使用拒绝策略
CallerRunsPolicy 使用这个策略的好处是不会抛出异常,当超出时就会回退到主线程中进行执行
合理配置线程数:
我们应该这么样去配置线程数?官方是核心数初始化是0,有就执行,没有就不执行,那么我们应该怎么样去配置?
这时候我们要考虑2点
CPU密集
IO密集的问题去思考合理的配置 核心线程数
加入群聊一起学习: