1.线程池基础概念
线程池是一种资源复用技术,通过预先创建并管理一组线程,减少频繁创建和销毁线程的开销。核心思想与数据库连接池、字符串常量池类似,旨在提升系统性能。
核心参数解析
ThreadPoolExecutor
构造函数包含7个关键参数:corePoolSize
:核心线程数,长期保持活跃的线程数量。maximumPoolSize
:线程池最大容量,包括核心线程和非核心线程。keepAliveTime
:非核心线程空闲存活时间。unit
:存活时间单位(如秒、毫秒)。workQueue
:任务队列,用于存放待执行任务(如ArrayBlockingQueue
、LinkedBlockingQueue
)。threadFactory
:自定义线程创建逻辑。handler
:拒绝策略(如AbortPolicy
抛出异常、CallerRunsPolicy
由提交线程执行任务)。
线程池工作流程
- 任务提交后,优先使用核心线程处理。
- 核心线程全忙时,任务进入工作队列。
- 队列满后,启用非核心线程(不超过
maximumPoolSize
)。 - 线程和队列均满时,触发拒绝策略。
拒绝策略类型
AbortPolicy
:直接抛出RejectedExecutionException
。CallerRunsPolicy
:提交任务的线程自行执行任务。DiscardOldestPolicy
:丢弃队列中最老的任务。DiscardPolicy
:静默丢弃新提交的任务。
任务提交方法
execute(Runnable task)
:无返回值,适用于异步任务。submit(Callable<T> task)
:返回Future<T>
,可获取执行结果。
线程池关闭
shutdown()
:平滑关闭,等待所有任务完成。shutdownNow()
:立即中断所有线程,返回未执行任务列表。2.线程池的工作流程
3.ThreadLocal原理与应用
ThreadLocal为每个线程提供独立的变量副本,解决多线程共享变量的线程安全问题。
基本使用
static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 1);public static void main(String[] args) {new Thread(() -> {threadLocal.set(10);threadLocal.set(threadLocal.get() + 5);System.out.println(Thread.currentThread().getName() + ":" + threadLocal.get());threadLocal.remove(); // 防止内存泄漏}).start();new Thread(() -> {threadLocal.set(20);threadLocal.set(threadLocal.get() + 10);System.out.println(Thread.currentThread().getName() + ":" + threadLocal.get());threadLocal.remove();}).start();
}
内存泄漏问题
ThreadLocal的键(ThreadLocal对象)被弱引用管理,值(变量副本)为强引用。若ThreadLocal实例被回收,但线程未终止,Entry中的值会持续占用内存。
解决方案:
- 显式调用
remove()
清理Entry。 - 避免长生命周期线程(如线程池线程)使用ThreadLocal时未清理。
引用类型对比
- 强引用:对象被直接引用,不会被GC回收(
Object obj = new Object()
)。 - 软引用(
SoftReference
):内存不足时回收,适合缓存场景。 - 弱引用(
WeakReference
):GC时立即回收,常用于ThreadLocal键。
线程创建方式总结
- 继承Thread类:重写
run()
方法。 - 实现Runnable接口:更灵活,推荐使用。
- 实现Callable接口:可返回结果,配合
FutureTask
使用。 - 线程池:高效管理线程资源,实际开发首选。
通过合理使用线程池和ThreadLocal,可显著提升多线程程序的性能和安全性。