你了解Java线程池的原理吗?
重要内容
Java 线程池(Executor)是 Java 提供的一种用于管理和重用线程的机制,通过它可以避免频繁创建和销毁线程的开销,提高程序的性能
线程池的工作流程
当我们向线程池提交任务时,线程池会按照以下步骤处理
- 检查核心线程数量:如果线程池中的线程数小于核心线程数,线程池会立即创建新的线程来执行任务
- 检查任务队列:如果线程池中的线程数已达到核心线程数,新的任务会被添加到任务队列中,等待有线程空闲时执行
- 检查最大线程数:如果任务队列已满,线程池会检查线程数是否小于最大线程数。如果小于,线程池会创建新的线程来执行任务
- 拒绝策略:如果线程池中的线程数达到了最大线程数,且任务队列已满,线程池会根据设定的拒绝策略来处理新任务
扩展内容
线程池的组成
Java 线程池主要由以下几部分组成
public ThreadPoolExecutor( int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 空闲存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 工作队列
ThreadFactory threadFactory, //线程工厂
RejectedExecutionHandler handler) // 拒绝策略
- 线程池核心线程:线程池启动时会创建的线程数量,这些线程会一直保持存活,除非线程池关闭或发生一些特殊情况(比如
allowCoreThreadTimeOut设置为true时,核心线程也可以在空闲一定时间后被回收) - 最大线程数:线程池中线程的最大数量。即使所有核心线程都在工作,线程池也可以通过创建新的线程来处理更多的任务,直到达到最大线程数
- 工作队列:线程池使用的队列,用于存放待执行的任务
LinkedBlockingQueue:基于链表的阻塞队列,支持无限任务排队ArrayBlockingQueue:固定长度的阻塞队列,任务队列长度有限SynchronousQueue:特殊的队列,它不存储任何任务,每当有新任务到来时,必须有空闲线程才能执行PriorityBlockingQueue:带优先级的无界阻塞队列
- 拒绝策略:当线程池中的线程数达到最大线程数,且任务队列已满时,线程池会根据设定的拒绝策略来处理新的任务
AbortPolicy:抛出RejectedExecutionException异常CallerRunsPolicy:由调用线程执行任务,避免线程池崩溃DiscardPolicy:丢弃任务,不抛出异常DiscardOldestPolicy:丢弃任务队列中最旧的任务
图解线程池的工作流程
如果线程池中的线程数小于核心线程数,线程池会立即创建新的线程来执行任务
如果线程池中的线程数已达到核心线程数,新的任务会被添加到任务队列中,等待有线程空闲时执行
如果任务队列已满,线程池会检查线程数是否小于最大线程数。如果小于,线程池会创建新的线程来执行任务
如果线程池中的线程数达到了最大线程数,且任务队列已满,线程池会根据设定的拒绝策略来处理新任务