线程池
作用:控制线程的数量,减少线程的创建和销毁
ThreadPoolExecutor
一、构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
lockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
前三个构造函数都是调用第四个构造函数进行初始化的。
参数:
- corePoolSize:
核心线程池的大小。在创建了线程池后,默认情况下,线程池中的线程数为0,当有任务来时,就会创建一个线程去执行任务。调用prestartAllCoreThreads()方法可以预设corePoolSize数量的线程,调用prestartCoreThread()方法可以预设一个线程。 - maximumPoolSize:
线程池最大线程数,表示在线程池中最多能创建多少个线程。 - keepAliveTime:
无任务执行的线程的存活时间。默认情况下,当线程数大于corePoolSize时,keepAliveTime才生效。如果调用allowCoreThreadTimeOut(boolean value)方法,当线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程数为0。 - unit:
keepAliveTime的时间单位:
(1)TimeUnit.DAYS:天
(2)TimeUnit.HOURS:小时
(3)TimeUnit.MINUTES:分钟
(4)TimeUnit.SECONDS:秒
(5)TimeUnit.MILLISECONDS:毫秒
(6)TimeUnit.MICROSECONDS:微妙
(7)TimeUnit.NANOSECONDS:纳秒
- workQueue:
阻塞队列,用来存储等待执行的任务。workQueue的类型为BlockingQueue,通常可以取下面三种类型:
(1)ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;
(2)LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE
;
(3)SynchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。 - threadFactory:
线程工厂,主要用来创建线程。 - handler:
表示当拒绝处理任务时的策略:
(1)ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
(2)ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
(3)ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
(4)ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
二、主要方法
- execute():
向线程池提交一个任务,交由线程池去执行。 - submit():
向线程池提交一个任务,交由线程池去执行,能够返回任务执行的结果。还是调用execute()去提交任务,利用Future来获取任务执行结果。 - shutdown()
关闭线程池,此时线程池不再接受新的任务,它会等待所有任务执行完毕。 - shutdownNow()
关闭线程池,此时线程池不再接受新的任务,并且会去尝试终止正在执行的任务。
三、线程池状态
// 表示当前线程池的状态,它是一个volatile变量用来保证线程之间的可见性
volatile int runState;
// 当初始化线程池后,线程池处于RUNNING状态
static final int RUNNING = 0;
// 调用shutdown()方法时,线程池处于SHUTDOWN状态
static final int SHUTDOWN = 1;
// 调用shutdownNow()方法时,线程池处于STOP状态
static final int STOP = 2;
// 当线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态
static final int TERMINATED = 3;
线程池对于新任务的处理策略
线程池的种类
- newCachedThreadPool
可根据需要创建新线程的线程池。
特征:
(1)线程池中数量没有固定,可达到最大值(Interger. MAX_VALUE)
(2)可重复使用:有新任务时,若线程池中有空闲线程,则使用空闲线程执行任务,若无则创建新线程
(3)线程池中的线程会进行回收,回收默认时间为1分钟
适用范围:
执行大量小任务的场景
使用方式:
Executors.newCachedThreadPool();
- newFixedThreadPool
可重用固定线程数的线程池。
特征:
(1)线程池中数量固定
(2)可重复使用,在显示关闭之前,都将一直存在
(3)当线程数达到上限,新的任务需在队列中等待
适用范围:
执行长期的任务
使用方式:
//nThreads为线程的数量
Executors.newFixedThreadPool(int nThreads);
//nThreads为线程的数量,threadFactory为线程工厂
Executors.newFixedThreadPool(int nThreads,ThreadFactory threadFactory);
- newSingleThreadExecutor
只使用单个线程的线程池。
特征:
(1)线程池中数量固定,且只为1
(2)可重复使用,所有任务都使用这一个线程执行
(3)当线程数达到上限,新的任务需在队列中等待
适用范围:
多个任务按照顺序执行
使用方式:
Executors.newSingleThreadExecutor() ;
Executors.newSingleThreadExecutor(ThreadFactory threadFactory);
- newScheduleThreadPool
创建可延迟执行或定期执行的线程的线程池。
特征:
(1)线程池中数量固定
(2)可重复使用,在显示关闭之前,都将一直存在
(3)当线程数达到上限,新的任务需在队列中等待
(4) 线程可延迟执行或定期执行
适用范围:
需要延迟执行或定期执行的任务
使用方式:
Executors.newScheduledThreadPool(int corePoolSize);
Executors.newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);
- newSingleThreadScheduledExecutor
创建一个可延迟执行或定期执行的线程的线程池。
特征:
(1)线程池中数量固定,且只为1
(2)可重复使用,在显示关闭之前,都将一直存在,所有任务都使用这一个线程执行
(3)当线程数达到上限,新的任务需在队列中等待
(4) 线程可延迟执行或定期执行
适用范围:
多个任务需要顺序的延迟执行或定期执行
使用方式:
Executors.newSingleThreadScheduledExecutor();
Executors.newSingleThreadScheduledExecutor(ThreadFactory threadFactory);
参考:[Java并发编程:线程池的使用](https://www.cnblogs.com/dolphin0520/p/3932921.html)