Java线程池架构(一)原理和源码解析(Java线程池原理及源码深度解析(一))

原创
ithorizon 6个月前 (10-20) 阅读数 15 #后端开发

Java线程池架构(一):原理和源码解析

一、Java线程池简介

Java线程池是一种用于管理多个线程的工具,它能够有效地管理线程的生命周期,尽或许降低损耗程序性能。Java线程池的核心是Executor框架,它提供了线程池的创建、管理以及任务提交等功能。在Java中,线程池的实现重点是通过ThreadPoolExecutor类来完成的。

二、线程池的核心参数

线程池的核心参数包括以下几个:

  • corePoolSize:线程池的基本大小。
  • maximumPoolSize:线程池最大线程数。
  • keepAliveTime:当线程数大于核心线程数时,这是多余空闲线程在终止前等待新任务的最长时间。
  • unit:keepAliveTime的时间单位。
  • workQueue:工作队列,用于存放还未执行的任务。
  • threadFactory:线程工厂,用于创建新线程。
  • handler:拒绝策略,当任务太多无法处理时,采取的策略。

三、线程池的工作流程

线程池的工作流程可以分为以下几个步骤:

  1. 当有新任务提交时,首先检查线程池中的线程数量是否小于corePoolSize。
  2. 如果小于corePoolSize,则创建新线程来执行任务。
  3. 如果线程池中的线程数量大于等于corePoolSize,但小于maximumPoolSize,并且工作队列未满,则将任务放入工作队列。
  4. 如果工作队列已满,但线程池中的线程数量小于maximumPoolSize,则创建新线程来执行任务。
  5. 如果线程池中的线程数量等于maximumPoolSize,则采取拒绝策略处理任务。

四、源码解析

下面我们来分析ThreadPoolExecutor类的核心源码。

4.1 类的继承结构

public class ThreadPoolExecutor extends AbstractExecutorService

implements ExecutorService {

// ...

}

ThreadPoolExecutor类继承了AbstractExecutorService类,并实现了ExecutorService接口。AbstractExecutorService类提供了线程池的基本实现,而ExecutorService接口定义了线程池的核心方法。

4.2 构造方法

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue 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.corePoolSize = corePoolSize;

this.maximumPoolSize = maximumPoolSize;

this.keepAliveTime = unit.toNanos(keepAliveTime);

this.workQueue = workQueue;

this.threadFactory = threadFactory;

this.handler = handler;

}

构造方法接收了线程池的核心参数,并对参数进行了校验。然后,将这些参数赋值给类的成员变量。

4.3 execute方法

public void execute(Runnable command) {

if (command == null)

throw new NullPointerException();

int c = ctl.get();

if (workerCountOf(c) < corePoolSize) {

if (addWorker(command, true))

return;

c = ctl.get();

}

if (isRunning(c) && workQueue.offer(command)) {

int recheck = ctl.get();

if (!isRunning(recheck) && remove(command))

reject(command);

else if (workerCountOf(recheck) == 0)

addWorker(null, false);

}

else if (!addWorker(command, false))

reject(command);

}

execute方法是线程池的核心方法,用于提交任务。该方法首先检查任务是否为null,然后尝试创建新线程执行任务。如果线程池中的线程数量小于corePoolSize,则调用addWorker方法创建新线程。如果创建顺利,则直接返回。如果创建未果,则将任务放入工作队列。如果工作队列已满,则尝试创建新线程,如果仍然未果,则采取拒绝策略。

4.4 addWorker方法

private boolean addWorker(Runnable firstTask, boolean core) {

retry:

for (;;) {

int c = ctl.get();

int rs = runStateOf(c);

// Check if queue empty only if necessary.

if (rs >= SHUTDOWN &&

! (rs == SHUTDOWN &&

firstTask == null &&

! workQueue.isEmpty())) {

return false;

}

for (;;) {

int wc = workerCountOf(c);

if (wc >= CAPACITY ||

wc >= (core ? corePoolSize : maximumPoolSize)) {

return false;

}

if (compareAndIncrementWorkerCount(c))

break retry;

c = ctl.get(); // Re-read ctl

if (runStateOf(c) != rs)

continue retry;

}

}

boolean workerStarted = false;

Thread w = null;

try {

w = threadFactory.newThread(this);

final Thread t = w;

final Runnable firstTask = this.firstTask;

this.firstTask = null;

w.start();

workerStarted = true;

} catch (Throwable ex) {

// ...

}

return workerStarted;

}

addWorker方法是线程池中创建新线程的核心方法。该方法首先检查线程池的状态,然后检查线程池中的线程数量是否已约为上限。如果线程数量未约为上限,则通过threadFactory创建新线程,并启动线程。

五、总结

本文对Java线程池的原理进行了简要介绍,并分析了ThreadPoolExecutor类的核心源码。线程池是一种高效的任务管理工具,通过合理地配置线程池参数,可以尽或许降低损耗程序性能。在后续的文章中,我们将继续深入探讨线程池的其他方面,如线程池的拒绝策略、工作队列的选择等。


本文由IT视界版权所有,禁止未经同意的情况下转发

文章标签: 后端开发


热门