文章目录
- 叙述
- 线程池的实现原理
- 线程池的机制
- ThreadPoolExecutor
Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。
叙述
线程池的实现原理
当向线程池提交一个任务之后,线程池是如何处理这个任务的呢?我们来看一下线程池的主要处理流程。
- 线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下一个流程。
- 线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下一个流程。
- 线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
线程池的机制
- 如果正在运行的线程数 < coreSize,马上创建线程执行该task,不排队等待;
- 如果正在运行的线程数 >= coreSize,把该task放入阻塞队列;
- 如果队列已满 && 正在运行的线程数 < maximumPoolSize,创建新的线程执行该task;
- 如果队列已满 && 正在运行的线程数 >= maximumPoolSize,线程池调用handler的reject方法拒绝本次提交。
从worker线程自己的角度来看,当worker的task执行结束之后,循环从阻塞队列中取出任务执行。
ThreadPoolExecutor
创建线程池主要是ThreadPoolExecutor类来完成,ThreadPoolExecutor的有许多重载的构造方法,通过参数最多的构造方法来理解创建线程池有哪些需要配置的参数。
ThreadPoolExecutor的构造方法:
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- corePoolSize:表示核心线程池的大小。
- maximumPoolSize:表示线程池能创建线程的最大个数。
- keepAliveTime:空闲线程存活时间。
- unit:时间单位。为keepAliveTime指定时间单位。
- workQueue:阻塞队列。用于保存任务的阻塞队列。可以使用ArrayBlockingQueue, LinkedBlockingQueue, SynchronousQueue,PriorityBlockingQueue。
- threadFactory:创建线程的工程类。
- handler:饱和策略。当线程池的阻塞队列已满和指定的线程都已经开启,说明当前线程池已经处于饱和状态了,那么就需要采用一种策略来处理这种情况。采用的策略有这几种:
- AbortPolicy: 直接拒绝所提交的任务,并抛出RejectedExecutionException异常;
- CallerRunsPolicy:只用调用者所在的线程来执行任务;
- DiscardPolicy:不处理直接丢弃掉任务;
- DiscardOldestPolicy:丢弃掉阻塞队列中存放时间最久的任务,执行当前任务
感谢您的阅读~~