线程池分四类:
1.newSingleThreadExecutor()
单个线程容量
截屏-20190926174255-801x168.png
2.newFixedThreadPool()
固定线程数量
截屏-20190926174436-834x132.png
3.newCachedThreadPool()
可根据实际情况调整线程数量
优先使用可复用的线程
截屏-20190926174515-776x146.png
4.newScheduledThreadPool()
线程数量为1,
可以固定时间延时执行任务
或周期性执行任务
截屏-20190926205643-932x108.png
public ThreadPoolExecutor(int corePoolSize,/*线程池中线程数*/
int maximumPoolSize,/*线程池中最大线程数*/
long keepAliveTime,/*当线程池线程数超过corePoolSize后,空闲线程的最大存活时间*/
TimeUnit unit,/*keepAliveTime单位*/
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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
前几个都很好理解,我们从workQueue开始
workQueue是指被提交但是未执行的任务队列,它是一个BlockingQueue接口对象,仅用于存Runnable对象,接下来看下可用的几种队列:
1.直接提交队列
由SynchronousQueue对象提供。
没有容量,目的就是为了实现拒绝策略,每一个插入操作都要等待相应的删除操作,反之,每一个删除操作都要等待相应的插入操作。
使用SynchronousQueue这种队列,提交的任务不会真正的保存,而是将新任务提交给线程,没有空闲线程,就新建一个,到达最大值了,就执行拒绝策略!
使用SynchronousQueue队列,通常要设置很大的maximumPoolSize的值,否则很容易执行拒绝策略。
2.有界任务队列(以ArrayBlockingQueue为例)
ArrayBlockingQueue的构造函数必须提供容量参数。
public ArrayBlockingQueue(int capacity)
使用ArrayBlockingQueue时,如果有新任务需要执行,
如果线程池的实际线程数小于corePoolSize,则会优先创建新的线程,
若大于corePoolSize,则会将新任务放进等待队列。
如果等队列已满,无法加入,
在总线程数不大于maximumPoolSize的前提下,创建新线程执行任务。
否则,执行拒绝策略。
3.无界任务队列(以LinkedBlockedQueue为例)
这种队列,除非系统资源耗尽,否则不存在任务入队失败的情况。
新任务来的时候
线程数小于corePoolSize时,线程池会生成新的线程执行任务,
等于corePoolSize后,就无限往等待队列里入队。
!!!!!如果处理速度远小于创建速度,等待队列就会很快增长,直到耗尽系统资源!!!!!
4.优先任务队列(通过PriorityBlockedQueue来实现)
PriorityBlockedQueue可以控制任务的执行先后顺序。是一个特殊的无界队列。
网友评论