首页 > 编程知识 正文

java线程池等待原理,连接池面试题

时间:2023-05-05 15:23:04 阅读:146676 作者:2402

处理器已经进入多核时代,为了充分利用cpu的多核资源,APP应用程序采用多线程并行/并行计算,充分利用多核来提高APP应用程序的性能。 但是,创建线程成本高昂,一方面需要内存资源,另一方面操作系统内核需要将线程添加到调度队列中,开销很大。 这一方面在高并发系统中性能风险非常大,另一方面线程需要消耗内存空间,如果不控制进程创建的线程数,进程的内存空间很可能会耗尽。

为了解决多线程上的两个问题,喜欢听歌的短靴设计了线程池。 线程池有两个主要作用。

1、在不同请求之间重用线程,不需要频繁创建和销毁线程,降低系统开销;

2 .控制线程数量上限,以避免创建过多的线程占用进程内存空间,同时减少线程上下文切换次数。

jdk在java5版本中添加了内置线程池,实现了ThreadPoolExecutor。 本文通过ThreadPoolExecutor的源代码分析线程池在jdk中的实现原理。

线程池由两个核心数据结构组成。

1 ) HashSet,用于存储执行线程集合(workers )任务的线程;

2 )任务等待队列(工作队列) :存储等待线程池调度执行的任务的块队列阻塞队列;

线程池中有几个核心参数。

任务执行过程

任务由execute方法提交到线程池,在提交任务时可能会出现以下情况:

1 )线程池中的线程数少于corePoolSize。 在这种情况下,任务不排队,线程池直接创建线程工作器并执行提交的任务;

2 )如果线程池中的线程数大于或等于corePoolSize,且队列不满,则任务直接添加到队列中,等待线程池的调度执行;

3 )如果线程池中的线程数大于或等于corePoolSize,但队列已满且线程数小于maximumPoolSize,则线程池将扩展,新创建的线程工作器将执行提交任务

4 )如果队列已满,线程数达到maximumPoolSize,则如果线程池无法继续执行任务,任务将被拒绝,指定的拒绝策略将运行。

5 )线程池已关闭。 拒绝任务并运行指定的拒绝策略。

创建线程后,它将继续从队列工作队列中执行任务。 因为工作队列是线程安全的块队列,所以没有线程安全问题。 拉入任务后,运行任务逻辑。 提取任务时有两种情况:

1 )线程池中设置了keepAliveTime参数,此时线程池中的线程数超过核心数corePoolSize,从队列读取任务时将keepAliveTime设置为超时时间超过此时间后,该线程将直接运行run方法主体,而不等待任务,线程将被回收。

2 )否则,线程无限期地等待任务队列,直到任务到来。

拒绝策略(RejectedExecutionHandler )。

当线程集合和等待队列已满时,线程将无法调度任务,线程池将执行默认或用户指定的拒绝策略。

JDK内置的拒绝策略主要包括:

1 )调用“线程执行”(CallerRunsPolicy ),如果任务被线程池拒绝,则任务调用线程执行。

2 )中止执行(AbortPolicy ),如果任务被拒绝,则抛出RejectedExecutionException异常

3 )放弃任务(DiscardPolicy ),直接放弃任务,不抛出异常报告错误;

4 )丢失旧任务(DiscardOldestPolicy ),删除队列中最旧的任务,删除后重新提交当前任务。

除了这些内置拒绝策略外,用户还可以实现RejectedExecutionHandler接口的自定义拒绝策略

关闭线程池

关闭线程池有两个重要步骤。

1 )将线程池的状态更改为关闭。 在这种情况下,新提交到线程池的任务将被直接拒绝。

2 )中断线程池中的所有线程,中断任务执行以回收线程集合中的所有线程。

按计划调度线程池(ScheduledThreadPoolExecutor )。

JDK还包含延迟/定时计划任务的线程池,用于延迟/定时执行已提交的任务。 与常规线程池实现的区别在于,任务队列使用自定义的阻塞队列DelayedWorkQueue,它按时间顺序对添加到队列中的任务进行排序。 从队列中提取任务时,只有在队列标头中的任务超过指定时间时,任务才会出队,否则等待。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。