Android线程池有哪些?他们的区别是什么?为什么要使用线程池?

本文介绍了Android中的四种线程池:FixedThreadPool、CachedThreadPool、SingleThreadPool 和 ScheduledThreadPool,并详细阐述了它们的特点及底层实现方式。此外,还探讨了使用线程池的好处以及如何自定义线程池。

Android线程池有哪些?他们的区别?

Android线程池都是机遇ThreadPoolExecutor实现的分为以下四种,都是通过Executors静态工厂创建出来的

FixedThreadPool 可以设置固定核心线程数,没有非核心线程 底层实现是LinkedBlockingQueue 

CashedThreadPool 没有核心线程数,可以创建非核心线程,有超时限制 底层实现是SynchronousQueue 没有存储空间所以进来的都会阻塞,拿洗盘子举例他就是没有盘架,洗完了直接放到烘干机中。从而降低了生产者到消费者之间的延迟

SingleThreadPool 只有一个核心线程 底层实现是LinkedBlockingQueue

ScheduleThreadPool 可以实现定期执行任务的线程池,有核心线程,也有非核心线程 底层实现是DelayWorkQueue

为什么使用线程池?

便于线程的管理,减少线程创建对于性能的消耗(性能消耗在哪里了?创建线程时候是要虚拟机上分配,栈,静态方法栈,程序计数器)在扩展一下线程运行时都是有栈针的存储当前执行到哪里了,当线程切换到的时候,就是保存被切换的栈针,寻找切换栈针的一个过程所有线程在切换的时候性能消耗也是很大的

如何自定义线程池?

要定义存储Runnable的队列,用于存储生产出的任务

定义核心线程池数

定义最大线程池数

定义线程超时控制

对于线程池工作流程可参看ThreadPoolExecutor内部原理






<think>我们正在讨论Java线程池中的任务队列类型及其区别。根据引用[3],线程池中的队列主要用于存放等待执行的任务,常见的队列类型包括无界队列、有界队列特殊队列。下面将详细说明每种队列及其适用场景。 ### 1. **无界队列(Unbounded Queue)** - **代表实现**:`LinkedBlockingQueue`(默认无界) - **特点**: - 容量为`Integer.MAX_VALUE`(约21亿),可视为无界。 - 任务提交速度超过处理速度时,队列会无限增长,可能导致内存溢出(OOM)。 - **适用场景**: - 任务量波动大,且不能容忍任务被拒绝的场景(如日志记录、异步消息处理)。 - **注意**:需确保任务增长速度可控,避免OOM[^3]。 ### 2. **有界队列(Bounded Queue)** - **代表实现**: - `ArrayBlockingQueue`:基于数组的固定容量队列。 - `LinkedBlockingQueue`(指定容量):可设置为有界模式。 - **特点**: - 队列容量固定,避免无限制增长。 - 当队列满且线程数未达`maximumPoolSize`时,会创建新线程;若线程数已达上限,则触发拒绝策略。 - **适用场景**: - 需要控制资源使用的场景(如高并发系统),防止内存溢出[^3]。 ### 3. **直接移交队列(Synchronous Queue)** - **代表实现**:`SynchronousQueue` - **特点**: - 容量为0,不存储任务。 - 新任务直接交给空闲线程,若无空闲线程则立即创建新线程(需满足`maximumPoolSize`限制)。 - 若线程数已达上限且无空闲线程,则触发拒绝策略。 - **适用场景**: - 高响应需求,任务处理必须即时分配线程(如实时交易系统)[^3]。 ### 4. **优先级队列(Priority Queue)** - **代表实现**:`PriorityBlockingQueue` - **特点**: - 任务按优先级排序(需实现`Comparable`接口或提供`Comparator`)。 - 可设为无界或有界(通常无界)。 - **适用场景**: - 需要按优先级处理任务的场景(如紧急事件插队处理)[^3]。 --- ### 队列对比表 | **队列类型** | **容量** | **是否阻塞** | **特点** | **适用场景** | |--------------------|----------------|-------------|--------------------------------------------------------------------------|----------------------------------| | `LinkedBlockingQueue` | 默认无界(可设限) | 阻塞 | 基于链表,FIFO | 通用异步任务处理 | | `ArrayBlockingQueue` | 固定有界 | 阻塞 | 基于数组,FIFO,性能稳定 | 资源受限的高并发系统 | | `SynchronousQueue` | 0 | 阻塞 | 直接移交任务,不存储 | 高响应实时系统 | | `PriorityBlockingQueue` | 无界(可设限) | 阻塞 | 按优先级排序 | 需任务优先级的场景 | | `DelayQueue` | 无界 | 阻塞 | 存储延时任务,到期才执行 | 定时任务调度(如缓存过期清理) | > ⚠️ **关键区别**: > - **有界 vs 无界**:有界队列控制内存风险,无界队列避免任务拒绝。 > - **存储机制**:`SynchronousQueue`直接移交任务,其他队列需缓冲。 > - **排序方式**:仅`PriorityBlockingQueue`支持优先级调度。 --- ### 队列选择策略 1. **避免OOM**:优先使用有界队列(如`ArrayBlockingQueue`),并设置合理的拒绝策略。 2. **任务优先级**:使用`PriorityBlockingQueue`实现紧急任务优先处理。 3. **高吞吐场景**:无界队列`LinkedBlockingQueue`适合异步处理大量非紧急任务。 4. **零延迟需求**:`SynchronousQueue`确保任务即时分配线程,但需警惕线程数爆炸。 --- ### 示例代码:不同队列的线程池配置 ```java // 1. 有界队列 + 拒绝策略 ThreadPoolExecutor boundedExecutor = new ThreadPoolExecutor( 5, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), // 容量100 new ThreadPoolExecutor.AbortPolicy() ); // 2. 无界队列(慎用) ThreadPoolExecutor unboundedExecutor = new ThreadPoolExecutor( 5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), // 默认无界 new ThreadPoolExecutor.CallerRunsPolicy() ); // 3. 直接移交队列 ThreadPoolExecutor synchronousExecutor = new ThreadPoolExecutor( 5, 100, 60, TimeUnit.SECONDS, // 最大线程数需较大 new SynchronousQueue<>(), new ThreadPoolExecutor.DiscardOldestPolicy() ); ``` --- ### 📚 相关问题延伸 1. **如何根据业务场景选择合适的队列?** (分析电商秒杀系统 vs 后台日志系统的队列选择差异) 2. **有界队列的容量如何科学设置?** (结合系统负载、任务特性监控指标的设计方法) 3. **`PriorityBlockingQueue`中任务优先级反转问题如何解决?** (优先级调度中的常见陷阱与规避方案) 4. **为什么`SynchronousQueue`可能导致线程数激增?** (对比其与无界队列的资源消耗模型) 5. **`DelayQueue`在定时任务调度中的实战案例** (如订单超时自动取消的实现原理)</think>### Java线程池任务队列类型详解 Java线程池支持多种任务队列实现,它们在数据结构、容量限制适用场景上有显著差异。以下是核心队列类型及其区别: #### 1. **无界队列(Unbounded Queue)** - **代表实现**:`LinkedBlockingQueue`(默认无界) - **特点**: - 容量为`Integer.MAX_VALUE`(约21亿),可视为无限容量 - 任务提交速度 > 处理速度时,队列会无限增长 - **优点**:永不触发拒绝策略,保证任务不丢失 - **缺点**:可能导致OOM(内存溢出) - **适用场景**: - 任务量波动大的**后台异步处理**(如日志记录) - 对任务丢失容忍度低的场景 ```java // 典型配置 new ThreadPoolExecutor( 5, 5, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>() // 无界队列 ); ``` #### 2. **有界队列(Bounded Queue)** - **代表实现**: - `ArrayBlockingQueue`(基于数组) - `LinkedBlockingQueue`(指定容量) - **特点**: - 固定容量(需构造函数指定) - 队列满时触发线程扩容(直到达到`maximumPoolSize`) - **优点**:内存可控,避免OOM - **缺点**:需合理设置容量,否则易触发拒绝策略 - **适用场景**: - **高并发系统**(如电商秒杀) - 需要严格控制资源使用的场景 ```java new ThreadPoolExecutor( 5, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100) // 容量100 ); ``` #### 3. **直接移交队列(Synchronous Queue)** - **代表实现**:`SynchronousQueue` - **特点**: - **容量为0**,不存储任务 - 新任务直接交给空闲线程,无空闲线程则立即创建新线程 - 线程数达上限时直接触发拒绝策略 - **优点**:任务响应延迟最低 - **缺点**:易触发线程数激增 - **适用场景**: - **高响应实时系统**(如金融交易) - 短任务且线程数上限合理的场景 ```java new ThreadPoolExecutor( 0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue<>() // 零容量队列 ); ``` #### 4. **优先级队列(Priority Queue)** - **代表实现**:`PriorityBlockingQueue` - **特点**: - 任务按优先级排序(需实现`Comparable`接口) - 可设为无界或有界 - **优点**:支持任务插队处理 - **缺点**:排序消耗额外性能 - **适用场景**: - **紧急任务优先处理**(如告警系统) - 需要动态调整任务顺序的场景 ```java // 自定义优先级比较器 PriorityBlockingQueue<Runnable> queue = new PriorityBlockingQueue<>(11, (a,b) -> a.getPriority() - b.getPriority()); ``` #### 5. **延迟队列(Delay Queue)** - **代表实现**:`DelayQueue` - **特点**: - 存储实现`Delayed`接口的任务 - 任务到期后才可被取出执行 - **优点**:内置定时调度能力 - **缺点**:不适用即时任务 - **适用场景**: - **定时任务调度**(如缓存过期清理) - 周期性任务执行 ```java ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2); executor.schedule(() -> cleanCache(), 5, TimeUnit.MINUTES); // 5分钟后执行 ``` --- ### 关键区别对比表 | **队列类型** | 容量 | 是否阻塞 | 排序能力 | 内存风险 | 典型用例 | |--------------------|------------|----------|----------|----------|------------------------| | `LinkedBlockingQueue` | 无界/有界 | ✅ | ❌ | 高 | 日志异步处理 | | `ArrayBlockingQueue` | 固定有界 | ✅ | ❌ | 低 | 高并发请求缓冲 | | `SynchronousQueue` | 0 | ✅ | ❌ | 低 | 实时交易系统 | | `PriorityBlockingQueue` | 无界/有界 | ✅ | ✅ | 中 | 紧急事件优先处理 | | `DelayQueue` | 无界 | ✅ | ✅ | 中 | 定时任务调度 | --- ### 队列选择策略 1. **优先考虑有界队列**:生产环境推荐`ArrayBlockingQueue`,需结合压测设置合理容量 2. **警惕无界队列**:仅当任务量绝对可控时使用`LinkedBlockingQueue` 3. **实时性要求**:超低延迟场景选`SynchronousQueue`,但需严格限制`maximumPoolSize` 4. **特殊需求**: - 优先级调度 → `PriorityBlockingQueue` - 定时任务 → `DelayQueue`(或直接使用`ScheduledThreadPoolExecutor`) > ⚠️ **阿里巴巴开发规约警示**:禁止使用`Executors.newFixedThreadPool()`(隐含无界队列风险)[^3] --- ### 📚 相关问题延伸 1. **如何根据CPU核心数设置队列容量?** (队列长度与线程数的黄金比例计算) 2. **有界队列满时如何设计拒绝策略?** (对比`CallerRunsPolicy`与自定义降级策略的优劣) 3. **为什么`SynchronousQueue`在Android线程池中被广泛使用?** (移动端低延迟场景的适配原理) 4. **优先级队列是否会导致低优先级任务饥饿?** (公平性保障机制的设计方案) 5. **如何监控队列堆积风险?** (基于`ThreadPoolExecutor#getQueue().size()`的告警实现)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值