项目中是如何创建线程池的,为什么不用Executors 去创建线程池

引用阿里巴巴Java开发手册上的一句话

【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:
1)FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

通过Executors创建一个定长线程池,示例(不要使用)

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

严格来说,使用此代码创建线程池时,是不符合编程规范的。

因为主要问题是定长线程池允许的请求队列长度为 Integer.MAX_VALUE,堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。

 

通过手动调用ThreadPoolExecutor去创建线程池

比如我们在Executors.newFixedThreadPool基础上给LinkedBlockingQueue加一个容量,当队列已经满了,而仍需要添加新的请求会抛出相应异常,我们可以根据异常做相应处理。

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>(10)); //添加容量大小
}

除了自己定义ThreadPoolExecutor外,还可以利用其它开源类库,如guava等,可以有更多个性化配置。

Spring配置线程池

spring配置线程池方式:自定义线程工厂bean需要实现ThreadFactory,可参考该接口的其它默认实现类,使用方式直接注入bean
调用execute(Runnable task)方法即可

<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>


   userThreadPool.execute(thread);

 

posted @ 2023-02-24 15:15  景恩  阅读(136)  评论(2编辑  收藏  举报