⑴ Java线程池newFixedThreadPool源码分析
本文深入探讨了Java线程池的创建与任务提交机制,以`newFixedThreadPool`为例进行源码分析。首先,`Executors.newFixedThreadPool()`创建线程池时,底层调用`ThreadPoolExecutor`的构造函数,核心与最大线程数默认值传入,线程存活时间默认为0毫秒。值得注意的是,`workQueue`底层采用`LinkedBlockingQueue`,容量设置为`Integer.MAX_VALUE`,意味着任务队列容量无限大,极端情况下可能导致内存溢出。
在自定义线程池时,用户需明确传入队列`workQueue`,并赋予其实际容量。`workQueue`内部实现为链表结构,初始化时设置`last`和`head`为`null`,在`execute`方法中再次涉及队列操作。进一步分析,`ThreadPoolExecutor`调用自身内部构造函数,核心参数保持一致,队列设置为`new LinkedBlockingQueue()`,工厂为默认线程工厂,过期策略默认为`AbortPolicy()`。
`ThreadPoolExecutor`继承自`AbstractExecutorService`,后者实现了`Executors`接口,提供了创建线程池的基础框架。创建线程池时,系统会进行一系列参数合法性检查,确保传入的参数合理,包括核心与最大线程数、存活时间等,同时验证队列、工厂、过期策略是否非空。
接着,我们将视线转移到`submit`方法,通过`submit()`向线程池提交任务。此操作实际由`AbstractExecutorService`实现,支持`Runnable`与`Callable`的提交,二者皆转为`RunnableFuture`。`newTaskFor`方法中,`FutureTask`类被构造,实现了`RunnableFuture`接口,继承了`Runnable`与`Future`。因此,`submit`方法最终生成`FutureTask`对象,通过`run`方法执行,实际由内部`callable`属性实现。
`execute(FutureTask)`方法由`ThreadPoolExecutor`实现,接收`FutureTask`作为参数。方法首先检查`FutureTask`是否为`null`,并进行相关注释。接着,进行一系列判断,包括线程池状态、队列容量与新任务状态等,确保线程池状态合法、任务与队列匹配。
在`addWorker`方法中,`ctl`变量被用于记录线程池的生命周期状态与当前工作线程数。`ctl`通过`ctlOf`方法封装`runState`与`workerCount`,并提供解封装方法,如`runStateOf`、`workerCountOf`等。`COUNT_BITS`与`CAPACITY`常量用于处理`ctl`变量的位操作,以实现高效状态管理。
`execute`方法执行逻辑分为两部分:一部分处理核心线程数与工作线程数的关系,通过`addWorker`方法动态扩展线程池;另一部分处理队列任务的提交与执行,确保线程池状态与任务需求相匹配。`addWorker`方法内部,通过CAS操作安全增加工作线程数,并根据线程池状态与新任务状态执行相应逻辑。`Worker`类作为线程执行器,继承`AbstractQueuedSynchronizer`,实现`Runnable`接口,封装任务执行逻辑。
`runWorker`方法实现线程执行逻辑,包括从队列获取任务、处理线程池状态与异常情况、执行任务与任务完成后的工作清理。`FutureTask`的`run`方法调用任务执行逻辑,并将结果存储在`outcome`中,供后续获取返回值。
`execute`方法第三部分处理线程池满载或核心线程数量时的扩展逻辑,通过队列`offer`方法添加任务,并根据线程池状态与队列容量调整工作线程数。`LinkedBlockingQueue`中的`offer`方法实现队列元素的添加,利用`AtomicInteger`类的`getAndIncrement`方法安全更新队列元素计数。`Condition`机制用于线程间的同步与唤醒,确保线程池与任务队列的高效管理。
总之,`newFixedThreadPool`源码展示了Java线程池管理的高效与灵活性。通过深入理解线程池的创建、任务提交与执行机制,开发者能够更好地利用线程池优化应用性能,解决并发编程中的资源管理与任务调度问题。本文仅提供了一个简要概述,实际源码细节与更多优化策略值得进一步探索与研究。