1. Java线程池类的组织架构
- Executor 最高级线程调度接口
- ExecutorService 通用线程池接口
- AbstractExecutorService
- ThreadPoolExecutor – 线程池实现类
- ScheduledExecutorService – 执行周期性任务的线程池实现类(不要用ExecutorService来引用)
- Executors – 线程池创建的静态工厂类
2. 使用线程池静态工厂Executors创建线程池
-
Executors.newSingleThreadExecutor(); // 创建只有一个线程的线程池 -
Executors.newFixedThreadPool(10); // 创建固定数量线程的线程池 -
Executors.newCachedThreadPool(); // 创建线程数动态调整的线程池,线程缓存时间为60S,最多创建Integer.MAX_VALUE 个线程 -
Executors.newScheduledThreadPool(5); // 创建一个周期性执行任务的线程池,
3. 核心线程池的内部实现 ?
? 查看源代码可以发现Executors 工厂类创建线程池的方法都是对 ThreadPoolExecutor 类的包装。
ThreadPoolExecutor构造函数:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
七个核心参数:
- corePoolSize 核心线程数,即使线程空闲也不会回收
- maximumPoolSize 最大线程数,线程池中可创建线程的上限
- keepAliveTime 多余线程的存活时间
- unit 存活时间的单位
- workQueue 任务队列,存放被提交后等待执行的任务
- threadFactory 线程工厂,用于创建线程,一般使用默认的
- handler 拒绝策略,当太多任务来不及处理要如何拒绝任务
任务队列(BlockingQueue)的具体实现:
-
SynchronousQueue 直接提交的队列:总是将新的任务直接提交给线程执行,如果没有空闲线程则进行创建,如果达到了最大线程数量限制就执行拒绝策略。如果设定了最大线程数为Integer.MAX_VALUE可能会导致创建出大量的线程耗尽系统资源。 -
ArrayBlockingQueue 有界任务队列:若线程池实际线程数小于corePoolSize则会优先创建线程,若大于corePoolSize会将任务提交到队列中进行等待,若队列已满而且线程数小于最大线程数则创建新线程执行,否则执行拒绝策略。 -
LinkedBlockingQueue 无界任务队列:除非资源耗尽,否则任务可以一直入队,有造成OOM的可能。 -
PriorityBlockingQueue 优先任务队列:该队列会先执行优先级高的任务。
线程工厂:
可对创建的线程进行定制,一般使用默认即可,
ThreadFactory threadFactory = Executors.defaultThreadFactory();
拒绝策略: 四种
AbortPolicy: 直接抛出异常,阻止系统正常工作(默认拒绝策略)。
CallerRunsPolicy: 交给调用线程(提交任务的线程)来处理该任务。
DiscardOldestPolicy: 丢弃最老的一个任务,并尝试提交当前任务。
DiscardPolicy: 丢弃无法处理的任务,不会抛出任何异常。
4. 为什么不推荐使用Executors创建线程池?
-
以Executors.newFixedThreadPool(10); 创建固定数量线程的线程池为例,他使用的是无界任务队列LinkedBlockingQueue ,当过多的任务提交过来又处理不完时任务不断被存放到无界任务队列中会造成队列长度不断增加,最后可能会导致OOM异常。 -
以newCachedThreadPool(); 创建动态数量线程的线程池为例,他在调用ThreadPoolExecutor创建线程池的时候将最大线程数设置为了Integer的最大值,当过多任务提交过来时可能会导致线程创建过多从而耗费了大量系统资源。
ps:推荐直接使用ThreadPoolExecutor类来直接创建线程池,让开发人员更了解线程池创建的核心参数。
5. 创建自定义线程池
public class CustomThreadPool {
public static class Task implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args) {
Task task = new Task();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
threadPoolExecutor.submit(task);
threadPoolExecutor.shutdown();
}
}
待补充:2021年10月23日23:10:14
- 自定义线程工厂threadFactory
- 自定义拒绝策略
参考《实战Java高并发程序设计》
|