当前位置: 首页 > 图灵资讯 > 技术篇> 多线程-线程池7大参数及其作用

多线程-线程池7大参数及其作用

来源:图灵教育
时间:2023-10-20 17:40:27

多线程-线程池的7个参数及其作用

public ThreadPoolExecutor(int corePoolSize, //核心线程池大小                          int maximumPoolSize, ///最大核心线程池的大小                          long keepAliveTime, ///超时释放                          TimeUnit unit, ///超时单位                          BlockingQueue<Runnable> 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;}
参数说明

<1>第一个参数:corePolSize线程池将维护一个线程数量最小,即使这些线程处于空闲状态,除非设置了allowcorethreadtimeout,否则它们也不会被销毁。这里的最小线程数量是corepolsize。这个参数设置非常关键。设置过度浪费资源,设置过小导致线程频繁创建或销毁。

<2>第2个参数:maximumPoolSize 任务提交到线程池后,首先会发现是否有空闲生存线程。如果是这样,它将直接执行。如果没有,它将被执行缓存到工作队列在中间,如果工作队列满了,将创建一个新的线程,然后从工作队列的头部取出一个任务,并将刚刚提交的任务放在工作队列的尾部。线程池不会无限制地创建新的线程,它会有最大线程数量的限制,这个数量是由maximunPolsize的数量减去corePolsize的数量来确定的,最多可以达到maximunPolsize,即最大线程池的线程数量。

<3>第三个参数:keepalivetime表示线程池中的线程空闲时间,当空闲时间达到keepalivetime值时,线程将被销毁,直到只剩下corepolsize线程,以避免浪费内存和句柄资源。

<4>第4个参数: TimeUnit表示时间单位。keepAliveTime 时间单位通常是TimeUnittt.SECONDS。

<5>第5个参数: workQueue 表示缓存队列。当要求的线程数大于corePolsize时,线程进入blockingQueue阻塞队列。

<6>第6个参数: threadFactory 表示线程工厂。它是用来表示的。生产一组相同任务的线程。通过在factory中添加组名前缀来实现线程池的命名。在虚拟机栈分析中,您可以知道线程任务是由哪个线程工厂生成的。

<7>第7个参数: handler 表示执行拒绝策略对象。当第五个参数workQueue的任务缓存区上限超过时,可以通过该策略处理请求,这是一种简单的限流保护。

Java线程池的四种拒绝策略 (1)拒绝时机

<1>第一种情况是我们调用它 shutdown 关闭线程池后,即使线程池内仍有未完成的任务,由于线程池已关闭,如果此时向线程池提交任务,也将被拒绝。

<2>第二种情况是线程池无法继续处理新提交的任务,也就是工作已经很饱和的时候。

(2)拒绝策略

<1>第一种是 AbortPolicy(默认)当拒绝任务时,这种拒绝策略会直接抛出一种类型 RejectedExecutionException 的 RuntimeException,让您感觉到任务被拒绝了,因此您可以根据业务逻辑选择重试或放弃提交等策略。

<2>第二种是 DiscardPolicy,这种拒绝策略就像它的名字所描述的那样,当新任务被直接丢弃时,它不会给你任何通知,因为我们不知道任务会被丢弃,这可能会导致数据丢失。

<3>第三种是 DiscardOldestPolicy,如果线程池未关闭且无法执行,则任务队列中的头结点将被丢弃,这通常是生存时间最长的任务。这一策略与第二个策略不同的是,它丢弃的不是最新提交的,而是队列中生存时间最长的,因此可以为新提交的任务腾出空间,但同样,也存在一定的数据丢失风险。

<4>第四种是 CallerRunsPolicy,相对而言,它是比较完美的,当有新的任务提交时,如果线程池未关闭,无法执行,将此任务交给提交任务的线程执行,即谁提交任务,谁负责执行任务。这样做有两个主要的好处:

①第一点新提交的任务不会丢弃,不会造成业务损失。 ②第二个好处是,由于任何提交任务的人都必须负责执行任务,因此提交任务的线程必须负责执行任务,而执行任务相对耗时。在此期间,提交任务的线程被占用,因此不会提交新任务,这减缓了提交任务的速度,相当于负面反馈。在此期间,线程池中的线程也可以充分利用这段时间执行部分任务,腾出一定的空间,相当于给线程池一定的缓冲期。