Java面试必备八股:Java并发之线程池

1 线程池有什么用

节省系统资源:频繁地创建和销毁线程会消耗系统资源,线程池能够复用已创建的线程。

提高响应速度:当任务到达时,任务可以不需要等待线程创建就立即执行。

【比如】当用户发起一个实时请求,服务器需要快速响应,此时如果每次请求都直接创建一个线程,那么线程的创建和销毁会消耗大量的系统资源。使用线程池,可以预先创建一定数量的线程,当用户请求到来时,直接从线程池中获取一个空闲线程,执行用户请求,执行完毕后,线程不销毁,而是继续保留在线程池中,等待下一个请求。

③除此之外,线程池支持定时执行、周期性执行、单线程执行和并发数控制等功能。

2 线程池工作流程

当应用程序提交一个任务时,线程池会根据当前线程的状态和参数决定如何处理这个任务。

如果当前线程数量小于核心线程数,线程池会直接创建一个新的线程来执行这个任务;

如果线程池中的核心线程都在忙,但任务队列未满,新提交的任务会被放入队列中进行等待;

如果任务队列已满,但当前线程数量小于最大线程数,线程池会创建新的线程来处理任务;

如果任务队列已满,且当前线程数量达到最大线程数,则线程池执行拒绝策略;

当某个任务执行完毕后,线程并不会立即销毁,而是继续保持在池中等待下一个任务;

线程空闲时间超出指定时间,且当前线程数大于核心线程数时,线程会被回收。

3 线程池主要参数

// 线程池主要参数有 7 个
ExecutorService threadPool = new ThreadPoolExecutor(
								int corePoolSize, // 核心线程数
								int maximumPoolSize,// 最大线程数
								long keepAliveTime,// 线程空闲时间(非核心线程空闲存活时间)
								TimeUnit unit,// 时间单位
								BlockingQueue<Runnable> workQueue, // 任务队列
								ThreadFactory threadFactory,// 线程工厂
								RejectedExecutionHandler handler// 拒绝策略
								);

corePoolSize 和 maximumPoolSize 共同定义了线程池的规模
当提交的任务数不足以填满核心线程时,线程池只会创建足够的线程来处理任务。
当任务数增多,超过核心线程的处理能力时,任务会被加入 workQueue。
如果 workQueue 已满,而当前线程数又小于 maximumPoolSize,线程池会尝试创建新的线程来处理任务。

keepAliveTime 和 unit 决定了非核心线程可以空闲存活多久。这会影响了线程池的资源回收策略

workQueue 的选择对线程池的行为有影响。不同类型的队列(如无界队列、有界队列)会导致线程池在任务增多时的反应不同。

handler 定义了线程池的饱和策略,即当线程池无法接受新任务时的行为。决定了系统在极限情况下的表现。

3 线程池的阻塞队列有哪些实现方式?

ArrayBlockingQueue:一个有界的先进先出阻塞队列,底层是一个数组,适合固定大小的线程池。

LinkedBlockingQueue:底层数据结构是链表,默认大小是 Integer.MAX_VALUE,相当于一个无界队列
Executors.newSingleThreadExecutor() (单线程的线程池)Executors.newFixedThreadPool()(固定线程数目的线程池) 都使用了该队列,前者适用于串行执行任务的场景,后者适用执行长期的任务。

PriorityBlockingQueue:一个支持优先级排序的无界队列。任务按照其自然顺序或通过构造器给定的 Comparator 来排序。适用于需要按照给定优先级处理任务的场景,比如优先处理紧急任务。

DelayQueue:类似于 PriorityBlockingQueue,由二叉堆实现的无界优先级队列
Executors.newScheduledThreadPool()(定时及周期执行的线程池) 就使用了该队列来实现延迟执行,适合周期性执行任务的场景。

SynchronousQueue:不是一个真正的队列,因为没有容量。每个插入操作必须等待另一个线程的移除操作。
Executors.newCachedThreadPool()(可缓存线程的线程池) 就使用了该队列,核心线程数为 0,这个线程池会根据需要创建新线程,如果有空闲线程则会重复使用,线程空闲 60 秒后会被回收。适用于并发执行大量短期的小任务。

4 线程池的四种拒绝策略

AbortPolicy:这是 默认 的拒绝策略。该策略会抛出一个 RejectedExecutionException 异常

CallerRunsPolicy:该策略不会抛出异常,而是会让提交任务的线程(即调用 execute 方法的线程)自己执行这个任务。

DiscardOldestPolicy丢弃队列中最老的一个任务(即队列中等待最久的任务),然后尝试重新提交被拒绝的任务。

DiscardPolicy丢弃该被拒绝的任务,不做任何处理也不抛出异常。【太坏了】

【如有错误或补充见解,欢迎留言交流和指正】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值