我们知道如果程序中并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束时,会因为频繁创建线程而大大降低系统的效率,因此出现了线程池的使用方式,它可以提前创建好线程来执行任务。本文主要通过java的ThreadPoolExecutor来查看线程池的内部处理过程。
1 ThreadPoolExecutor
java.uitl.concurrent.ThreadPoolExecutor类是线程池中最核心的一个类,下面我们来看一下ThreadPoolExecutor类的部分实现源码。
1.1 构造方法
ThreadPoolExecutor类提供了如下4个构造方法- // 设置线程池时指定核心线程数、最大线程数、线程存活时间及等待队列。
- // 线程创建工厂和拒绝策略使用默认的(AbortPolicy)
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue<Runnable> workQueue) {
- this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
- Executors.defaultThreadFactory(), defaultHandler);
- }
- // 设置线程池时指定核心线程数、最大线程数、线程存活时间、等待队列及线程创建工厂
- // 拒绝策略使用默认的(AbortPolicy)
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue<Runnable> workQueue,
- ThreadFactory threadFactory) {
- this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
- threadFactory, defaultHandler);
- }
- // 设置线程池时指定核心线程数、最大线程数、线程存活时间、等待队列及拒绝策略
- // 线程创建工厂使用默认的
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue<Runnable> workQueue,
- RejectedExecutionHandler handler) {
- this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
- Executors.defaultThreadFactory(), handler);
- }
- // 设置线程池时指定核心线程数、最大线程数、线程存活时间、等待队列、线程创建工厂及拒绝策略
- 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;
- }
复制代码 1.3 任务执行run方法
在上述addWorker中,当调用线程的start方法启动线程后,会执行其中的run方法。- public void execute(Runnable command) {
- // 判断提交的任务command是否为null,若是null,则抛出空指针异常;
- if (command == null)
- throw new NullPointerException();
- // 获取线程池中当前线程数
- int c = ctl.get();
- // 如果线程池中当前线程数小于核心池大小,进入if语句块
- if (workerCountOf(c) < corePoolSize) {
- // 如果以给定的命令启动一个核心线程执行任务成功,直接返回
- if (addWorker(command, true))
- return;
- c = ctl.get();
- }
- // 如果当前线程池处于RUNNING状态,则将任务放入任务缓存队列
- if (isRunning(c) && workQueue.offer(command)) {
- int recheck = ctl.get();
- // 如果线程池不处于运行状态并且移除刚加入的任务成功则执行拒绝策略
- if (! isRunning(recheck) && remove(command))
- reject(command);
- // 如果当前线程数为0,则在线程池里增加一个线程,保证队列里的任务不会没有线程执行
- else if (workerCountOf(recheck) == 0)
- addWorker(null, false);
- }
- // 尝试启动核心线程之外的线程,如果不满足,则执行对应的拒绝策略
- else if (!addWorker(command, false))
- reject(command);
- }
复制代码 2 整体处理过程
通过上述源码分析,我们可以得出线程池处理任务的过程如下:

3 总结
本文从源码层面主要分析了线程池的创建、运行过程,通过上述的分析,可以看出当线程池中的线程数量超过核心线程数后,会先将任务放入等待队列,队列放满后当最大线程数大于核心线程数时,才会创建新的线程执行。
作者:京东物流 管碧强
来源:京东云开发者社区 自猿其说Tech 转载请注明来源
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |