线程池:管理同一组同构工作线程的资源池
创建线程池
1、通过调用Executors中的静态工厂方法来创建线程池
newFixedThreadPool:固定长度的线程池
newCachedThreadPool:可缓存的线程池。如果线程池的当前规模超过了处理需求时,那么将回收空闲线程,而当需求增加时,则可以添加新的线程。线程池的规模不存在任何限制。
newSingleThreadExecutor :单线程的Executor,它创建单个工作者线程来执行任务,如果这个线程异常结束,会创建另一个线程来替代。newSingleThreadExecutor能确保依照任务在队列中的顺序来串行执行。
newScheduledThreadPool:创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务。
ExecutorService executorService = Executors.newFixedThreadPool(2);
在阿里巴巴java开发者手册中并不推荐使用Executors创建线程池:
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
2、ThreadPoolExecutor
TreadPoolExecutor是一个灵活的、稳定的线程池,允许进行各种定制。
TreadPoolExecutor一个通用构造函数:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
xml配置:
<bean id="myTaskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="20"/>
<property name="maxPoolSize" value="40"/>
<property name="queueCapacity" value="40"/>
<property name="keepAliveSeconds" value="30"/>
</bean>
corePoolSize
:线程池的基本大小,即在没有任务执行时线程池的大小,并且只有在工作队列满了的情况下才会创建超出基本大小的线程。
maxPoolSize
:线程池的最大大小,即可同时活动的线程数量的上限。
如果某个线程的空闲时间超过的存活时间keepAliveSeconds
,那么将被标记为可回收的,并且当线程池的当前大小超过了基本大小时,这个线程将被终止。
ThreadPoolExecutor允许提供一个BlockingQueue来保存等待执行的任务。基本的任务排队方法有3种:
- 无界队列
- 有界队列
- 同步移交
无界队列如无界的LinkedBlockingQueue
,如果所有工作线程都处于忙碌状态,那么任务将在队列中等候。如果任务持续快速到达,并且超过了线程池处理他们的速度,那么队列将无限制地增加。
有界队列是一种更为稳妥的管理策略,如ArrayBlockingQueue
,有界的LinkedBlockingQueue
,PriorityBlockingQueue
。
同步移交使用SynchronousQueue
来避免任务排队,以及直接将任务从生产者移交给工作者线程。SynchronousQueue不是一个真正的队列,而是一个线程之间进行移交的机制。将一个元素放入SynchronousQueue中,必须有另外一个线程正在等待接受这个元素。如果没有并且当前线程池的大小小于最大值,则创建一个新的线程,否则这个任务将被拒绝。
扩展ThreadPoolExecutor
ThreadPoolExecutor是可扩展的,它提供了几个可以在子类改写的方法:beforeExecute、afterExecute、terminated
public class MyThreadPoolExecutor extends ThreadPoolExecutor{
public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected void beforeExecute(Thread t,Runnable r){
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
}
@Override
protected void terminated() {
}
}
beforeExecute、afterExecute方法可以添加日志、计时、监视或统计信息的功能。无论任务是从run中正常返回,还是抛出异常,afterExecute方法都会被调用(如果任务完成后带一个Error,那么就不会调用afterExecute)。
在线程池完成关闭操作时调用terminated,terminated可以用来释放分配的各种资源、执行发送通知、记录日志或者收集finalize统计信息等操作。
参考:
《java并发编程实战》
https://blog.csdn.net/qq_33300570/article/details/78394188