ThreadPoolExecutor相关参数
迪丽瓦拉
2024-06-02 13:36:02
0

ThreadPoolExecutor完整参数构造器源码如下

/*** Creates a new {@code ThreadPoolExecutor} with the given initial* parameters.** @param corePoolSize the number of threads to keep in the pool, even*        if they are idle, unless {@code allowCoreThreadTimeOut} is set* @param maximumPoolSize the maximum number of threads to allow in the*        pool* @param keepAliveTime when the number of threads is greater than*        the core, this is the maximum time that excess idle threads*        will wait for new tasks before terminating.* @param unit the time unit for the {@code keepAliveTime} argument* @param workQueue the queue to use for holding tasks before they are*        executed.  This queue will hold only the {@code Runnable}*        tasks submitted by the {@code execute} method.* @param threadFactory the factory to use when the executor*        creates a new thread* @param handler the handler to use when execution is blocked*        because the thread bounds and queue capacities are reached* @throws IllegalArgumentException if one of the following holds:
* {@code corePoolSize < 0}
* {@code keepAliveTime < 0}
* {@code maximumPoolSize <= 0}
* {@code maximumPoolSize < corePoolSize}* @throws NullPointerException if {@code workQueue}* or {@code threadFactory} or {@code handler} is null*/ public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler; }

创建 ThreadPoolExecutor 实例

private int corePoolSize = Runtime.getRuntime().availableProcessors()+1;
private int maximumPoolSize = corePoolSize << 1;
private ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,1L,TimeUnit.HOURS,new LinkedBlockingQueue<>(1000),new CustomizableThreadFactory("update-data-"),new ThreadPoolExecutor.CallerRunsPolicy());

corePoolSize

线程池大小的合理设置

看当前线程池中要执行的任务是属于I/O密集型还是CPU密集型。

I/O密集型:线程频繁需要和磁盘或者远程网络通信,这种场景中磁盘的耗时和网络通信的耗时较大,意味着线程处于阻塞期间,不会占用CPU资源,所以线程数量设置超过CPU核心数并不会造成问题。

CPU密集型:对CPU利用率较高的场景,比如循环、递归、逻辑运算等,这种情况下线程数量设置越少,越能减少CPU的上下文频繁切换。

有一种建议如下,其中N表示CPU的核心数量。

  • I/O密集型,线程池大小设置为 2N+1。

  • CPU密集型,线程池大小设置为 N+1。

之所以需要+1,因为这样设置以后,线程在某个时刻发生一个页错误或者因为其他原因暂停时,刚好有一个额外的线程可以确保CPU周期不会中断。

workQueue

在创建的核心线程都在运行任务的情况下,后来的任务添加 workQueue 中。

一般使用的是 LinkedBlockingQueue,基于链表在内存中零散放置对象,不像 ArrayBlockingQueue 需要在内存中开启一段连续的内存空间,LinkedBlockingQueue 不指定容量默认是 Integer.MAX_VALUE,这个太大,可以自定义大小,看了很多,一般取 1000 为好。

maximumPoolSize

在 workQueue 中的任务都满了的情况下,添加任务到最外层的线程池。

看了很多说法,该参数设置为 corePoolSize 的两倍比较好。

threadFactory

线程工厂,需要实现 ThreadFactory 接口进行自定义实现。

如果未指定该参数,默认的线程工厂是 DefaultThreadFactory。

可以使用 spring 的 CustomizableThreadFactory,线程池名称需要单独指定名称,不然后面出现问题不好排查。

handler

线程池拒绝策略

当线程数已经达到maxPoolSize,且队列已满,会拒绝新任务。

当线程池被调用shutdown()后,会等待线程池里的任务执行完毕再shutdown。如果在调用shutdown()和线程池真正shutdown之间提交任务,会拒绝新任务。

RejectedExecutionHandler 接口的实现类,同 threadFactory 可以实现接口进行自定义实现。

java 内置的拒绝策略都是 ThreadPoolExecutor 的 静态内部类,如果未指定该参数,默认的拒绝策略是 AbortPolicy。

/*** The default rejected execution handler*/
private static final RejectedExecutionHandler defaultHandler =new AbortPolicy();

一般在实际开发中使用的是 CallerRunsPolicy,作用如下

当有新任务提交后,如果线程池没被关闭且没有能力执行,则把这个任务交于提交任务的线程执行,也就是谁提交任务,谁就负责执行任务。

keepAliveTime 和 unit

参见 https://blog.csdn.net/zlpzlpzyd/article/details/129347205

corePoolSize、workQueue、maximumPoolSize 的概念不好理解,可以看一下本人之前写的文章

https://blog.csdn.net/zlpzlpzyd/article/details/110298201

相关内容