一、使用线程池主要有以下三个原因
1)、创建/销毁线程需要消耗系统资源,线程池可以复用已创建的线程。
2)、控制并发的数量。并发数量过多,可能会导致资源消耗过多,从而造成服务器崩溃。(主要原因)
3)、可以对线程做统一管理
Java中的线程池顶层接口是Executor接口,ThreadPoolExecutor是这个接口的实现类。
二、ThreadPoolExecutor类 java.util.concurrent.ThreadPoolExecutor
/**
* 构造方法 5个参数
* @param corePoolSize 该线程池中核心线程数最大值
* @param maximumPoolSize 该线程池中线程总数最大值
* @param keepAliveTime 非核心线程闲置超时时长。
* @param unit keepAliveTime的单位 TimeUnit.MILLISECONDS 毫秒
* @param workQueue 阻塞队列,维护着等待执行的Runnable任务对象
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
/**
* 6个参数 6-1
* @param threadFactory 创建线程工厂,设置一些默认参数
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
/**
* 构造方法 6-2
* @param handler 线程数量大于最大线程数就会采用拒绝处理策略 ThreadPoolExecutor.CallerRunsPolicy 由调用线程处理该任务
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
/**
* 构造方法 6-3 6-1和6-2的结合
*/
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;
}
参数:
int corePoolSize:该线程池中核心线程数最大值
核心线程:线程池中有两类线程,核心线程和非核心线程。核心线程默认情况下会一直存在于线程池中,而非核心线程如果长时间的闲置,就会被销毁。
int maximumPoolSize:该线程池中线程总数最大值 。
该值等于核心线程数量 + 非核心线程数量。
long keepAliveTime:非核心线程闲置超时时长。
非核心线程如果处于闲置状态超过该值,就会被销毁。如果设置allowCoreThreadTimeOut(true),则会也作用于核心线程。
TimeUnit unit:keepAliveTime的单位。
NANOSECONDS : 1微毫秒 = 1微秒 / 1000 MICROSECONDS : 1微秒 = 1毫秒 / 1000
MILLISECONDS : 1毫秒 = 1秒 /1000 SECONDS : 秒 MINUTES : 分 HOURS : 小时 DAYS : 天
BlockingQueue workQueue:阻塞队列,维护着等待执行的Runnable任务对象。
几种常见的阻塞队列:
1,LinkedBlockingQueue:链式阻塞队列,底层数据结构是链表,默认大小是
Integer.MAX_VALUE
,也可以指定大小。 2,ArrayBlockingQueue:数组阻塞队列,底层数据结构是数组,需要指定队列的大小。
3,SynchronousQueue:同步队列,内部容量为0,每个put操作必须等待一个take操作,反之亦然。
4,DelayQueue:延迟队列,该队列中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素 。
ThreadFactory threadFactory :创建线程的工厂,用于批量创建线程。
RejectedExecutionHandler handler:拒绝处理策略,线程数量大于最大线程数就会采用拒绝处理策略。
ThreadPoolExecutor.AbortPolicy:默认拒绝处理策略,丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:丢弃新来的任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列头部(最旧的)的任务,然后重新尝试执行程序(如果再次失败,重复此过程)。
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务。
三、ThreadPoolExecutor的策略
线程池本身有一个调度线程,这个线程就是用于管理布控整个线程池里的各种任务和事务,例如创建线程、销毁线程、任务队列管理、线程队列管理等等。
故线程池也有自己的状态。
ThreadPoolExecutor
类中定义了一个volatile int
变量runState来表示线程池的状态 ,分别为RUNNING、SHUTDOWN、STOP、TIDYING 、TERMINATED。
线程池创建后处于RUNNING状态。
调用shutdown()方法后处于SHUTDOWN状态,线程池不能接受新的任务,清除一些空闲worker,会等待阻塞队列的任务完成。
调用shutdownNow()方法后处于STOP状态,线程池不能接受新的任务,中断所有线程,阻塞队列中没有被执行的任务全部丢弃。此时,poolsize=0,阻塞队列的size也为0。
当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。接着会执行terminated()函数。
ThreadPoolExecutor中有一个控制状态的属性叫ctl,它是一个AtomicInteger类型的变量。
线程池处在TIDYING状态时,执行完terminated()方法之后,就会由 TIDYING -> TERMINATED, 线程池被设置为TERMINATED状态。
四、四种常见的线程池
Executors
类中提供的四个静态方法来创建线程池
1、newCachedThreadPool
//创建一个核心线程数为0,线程总数为Integer.MAX_VALUE(2147483647),非核心线程60s超时,SynchronousQueue对列的线程池。创兼的只有非核心线程,线程闲置60s会被摧毁
//当需要执行很多短时间的任务时,CacheThreadPool的线程复用率比较高, 会显著的提高性能
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static void main(String[] args){
ExecutorService executorService = Executors.newCachedThreadPool();
for(int i = 0 ;i < 100;i ++){
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName());
});
}
//调用shutdown()方法后处于**SHUTDOWN**状态,线程池不能接受新的任务,清除一些空闲worker,会等待阻塞队列的任务完成。
executorService.shutdown();
}
2、newFixedThreadPool
//创建一个核心线程数和线程总数一样,线程不会被摧毁,LinkedBlockingQueue对列的线程池。创建的只有核心线程。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static void main(String[] args){
ExecutorService executorService = Executors.newFixedThreadPool (5);
for(int i = 0 ;i < 100;i ++){
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName());
});
}
//调用shutdown()方法后处于**SHUTDOWN**状态,线程池不能接受新的任务,清除一些空闲worker,会等待阻塞队列的任务完成。
executorService.shutdown();
}
3、newSingleThreadExecutor
//创建一个核心线程和总线程数都为1,LinkedBlockingQueue对列的线程池。只有一个核心线程。
//任务按照先来先执行的顺序执行
public static ExecutorService newSingleThreadExecutor() {
return new Executors.FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static void main(String[] args){
ExecutorService executorService = Executors.newSingleThreadExecutor();
for(int i = 0 ;i < 100;i ++){
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName());
});
}
//调用shutdown()方法后处于**SHUTDOWN**状态,线程池不能接受新的任务,清除一些空闲worker,会等待阻塞队列的任务完成。
executorService.shutdown();
}
4、newScheduledThreadPool
//定长的线程池,支持周期性执行任务
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new ScheduledThreadPoolExecutor.DelayedWorkQueue());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public static void main(String[] args){
//支持周期的执行任务
ScheduledExecutorService executorService = Executors.newScheduledThreadPool (1);
// 2 第一次执行任务2s后执行,3任务之间的周期为3秒,TimeUnit.SECONDS 2和3的时间单位
executorService.scheduleAtFixedRate(() ->{
System.out.println(System.currentTimeMillis());
},2,3, TimeUnit.SECONDS);
//调用shutdown()方法后处于**SHUTDOWN**状态,线程池不能接受新的任务,清除一些空闲worker,会等待阻塞队列的任务完成。
//executorService.shutdown();
}