一 、线程池
1.1 线程池简介:
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管带啦中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。
在线程池的使用上,线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让开发者更加明确线程池的运行规则,规避资源耗尽的风险。
不使用Executors的相关说明:Executors 返回的线程池对象的弊端如下:
1)FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool 和 ScheduledThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
1.2 ThreadPoolExecutor线程及构造函数即相关参数介绍:
// Java线程池的完整构造函数
public ThreadPoolExecutor(
int corePoolSize, // 线程池长期维持的核心线程数。
int maximumPoolSize, // 最大线程数,包含核心线程数在内最多可创建的线程数。
long keepAliveTime, TimeUnit unit, // 超过corePoolSize的非核心线程会被回收。
BlockingQueue<Runnable> workQueue, // 任务阻塞队列。
ThreadFactory threadFactory, // 新线程的生成工厂
RejectedExecutionHandler handler);// 任务的拒绝策略,即拒绝过剩任务
1.2.1 corePoolSize
该线程池中核心线程数最大值 。线程池新建线程的时候,如果当前线程总数小于corePoolSize,则新建的是核心线程,如果超过corePoolSize,则新建的是非核心线程核心线程默认情况下会一直存活在线程池中,即使这个核心线程啥也不干(闲置状态)。如果指定ThreadPoolExecutor的allowCoreThreadTimeOut这个属性为true,那么核心线程如果不干活(闲置状态)的话,超过一定时间(时长下面参数决定),就会被销毁掉。
1.2.2 maximumPoolSize
该线程池中线程总数最大值。线程总数 = 核心线程数 + 非核心线程数
1.2.3 keepAliveTime
该线程池中非核心线程限制超时时长。一个非核心线程,如果不干活(闲置状态)的时长超过这个参数所设定的时长,就会被销毁掉,如果设置allowCoreThreadTimeOut = true,则会作用于核心线程。
1.2.4 unit
keepAliveTime的单位,包括NANOSECONDS、MILLISECONDS、SECONDS、MICROSECONDS、MINUTES、HOURS、DAYS .
1.2.5 workQueue
该线程池中的任务队列:维护着等待执行的Runnable对象。当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务。
1.2.6 threadFactory
创建线程的方式,这是一个接口,你new他的时候需要实现他的Thread newThread(Runnable r)方法,一般用不上。一般都是采用Executors.defaultThreadFactory()方法返回的DefaultThreadFactory,当然也可以用其他的来设置更有意义的名称。
1.2.7 handler
拒绝策略。当使用有界队列,且队列任务被填满后,线程数也达到最大值时,拒绝策略开始发挥作用,ThreadPoolExecutor默认使用AbortPolicy拒绝策略。
1.3 线程池执行流程(此图来源其他技术博客,感觉很直观,借用):
释义:
1、当线程数小于 corePoolSize时,创建线程执行任务。
2、当线程数大于等于 corePoolSize并且 workQueue 没有满时,放入workQueue中
3、线程数大于等于 corePoolSize并且当 workQueue 满时,新任务新建线程运行,线程总数要小于 maximumPoolSize
4、当线程总数等于 maximumPoolSize 并且 workQueue 满了的时候执行 handler 的 rejectedExecution。也就是拒绝策略(图中的饱和策略)。
(不足之处请指明,谢谢!)