一 关于 ThreadPoolExecutor
转载:
https://www.cnblogs.com/dolphin0520/p/3932921.html
纠正:
1.在jdk1.8中,标识线程状态的runState,用 AtomicInteger ctl 来表示。
二 关于其他线程池
1.FixedThreadPool:
适用于为了满足资源管理需求,而需要限制当前线程数量的应用场景。它适用于负载比较重的服务器;
(1) .如果当前运行的线程数小于corePoolSize,则创建新的线程来执行任务;
(2).当前运行的线程数等于corePoolSize后,将任务加入LinkedBlockingQueue;
(3).线程执行完1中的任务后,会在循环中反复从LinkedBlockingQueue中获取任务来执行;
使用无界队列 LinkedBlockingQueue(队列的容量为Intger.MAX_VALUE)
2. SingleThreadExecutor
是使用单个worker线程的Executor,corePoolSize和maximumPoolSize都被设置为1.其他参数和FixedThreadPool相同
适用于需要保证顺序地执行各个任务并且在任意时间点,不会有多个线程是活动的应用场景。
(1)如果当前运行的线程数少于corePoolSize,则创建一个新的线程执行任务;
(2)当线程池中有一个运行的线程后,将任务加入LinkedBlockingQueue
(3)线程执行完1中的任务后,会在循环中反复从LinkedBlockingQueue中获取任务来执行;
。使用无界队列LinkedBlockingQueue(队列的容量为Intger.MAX_VALUE)
3 CachedThreadPool
适用于执行很多的短期异步任务的小程序,或者是负载较轻的服务器;
CachedThreadPool的corePoolSize被设置为空(0),maximumPoolSize被设置为Integer.MAX.VALUE,即它是无界的,这也就意味着如果主线程提交任务的速度高于maximumPool中线程处理任务的速度时,CachedThreadPool会不断创建新的线程。使用 SynchronousQueue队列(不存储元素的堵塞队列)
(1).首先向队列提交任务(offer)。如果当前有闲线程正在向队列索要任务,那么主线程执行offer操作与空闲线程执行的poll操作配对成功,主线程把任务交给空闲线程执行,execute()方法执行完成,否则执行下面的步骤2;
(2)当初始线程池为空,或者maximumPool中没有空闲线程时,将没有线程执行poll来执行任务。这种情况下,步骤1将失败,此时CachedThreadPool会创建新线程执行任务,execute方法执行完成;
4.ScheduledThreadPoolExecutor
适用于需要多个后台执行周期任务,同时为了满足资源管理需求而需要限制后台线程的数量的应用场景,
主要用来在给定的延迟后运行任务,或者定期执行任务。使用的任务队列DelayQueue(优先级队列)封装了一个PriorityQueue,PriorityQueue会对队列中的任务进行排序,执行所需时间短的放在前面先被执行(ScheduledFutureTask的time变量小的先执行),如果执行所需时间相同则先提交的任务将被先执行(ScheduledFutureTask的squenceNumber变量小的先执行)。
(1). 当调用ScheduledThreadPoolExecutor的 scheduleAtFixedRate() 方法或者scheduleWirhFixedDelay() 方法时,会向ScheduledThreadPoolExecutor的 DelayQueue 添加一个实现了 RunnableScheduledFutur 接口的 ScheduledFutureTask 。
( 2 ) 线程池中的线程从DelayQueue中获取ScheduledFutureTask,然后执行任务。
.
ScheduledThreadPoolExecutor执行周期任务的步骤
1.线程1从DelayQueue中获取已到期的ScheduledFutureTask(DelayQueue.take())。到期任务是指ScheduledFutureTask的time大于等于当前系统的时间;
2.线程1执行这个ScheduledFutureTask;
3.线程1修改ScheduledFutureTask的time变量为下次将要被执行的时间;
4.线程1把这个修改time之后的ScheduledFutureTask放回DelayQueue中(DelayQueue.add())。
5.弊端
Executors 返回线程池对象的弊端如下:
FixedThreadPool 和 SingleThreadExecutor : 允许请求的队列长度为 Integer.MAX_VALUE,可能堆积大量的请求,从而导致OOM。
CachedThreadPool 和 ScheduledThreadPool : 允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致OOM。