在手写线程池时,通常选择使用 有界队列 或 无界队列,具体选择哪一种取决于具体的应用场景和需求。下面是每种队列的优缺点,并解释为什么在手写线程池时通常选择其中的某些队列。
1. 有界队列(ArrayBlockingQueue
)
- 使用场景:对于大多数场景,尤其是当任务数量较为稳定或可控时,有界队列 是一个较好的选择。它通常用于大多数生产环境中的线程池设计中。
为什么使用:有界队列的最大优势是可以限制线程池中任务的数量,防止任务积压造成内存耗尽或系统崩溃。
- 例如:假设我们设定了最大线程数(比如 10 个线程),同时设定队列容量(比如 100 个任务)。当队列满时,线程池会拒绝新的任务或者阻塞提交任务的线程,直到队列有空闲位置。这种机制有效避免了内存爆炸和资源超载。
- 优点:有界队列能有效防止任务数量过多导致内存泄漏等问题,保证系统的稳定性,能够帮助我们实现合理的负载控制。
- 缺点:如果任务提交速度过快,队列满了,后续任务可能会被拒绝或需要长时间阻塞。
常见队列选择:
ArrayBlockingQueue
代码示例:
ExecutorService executorService = new ThreadPoolExecutor( 4, // corePoolSize 10, // maximumPoolSize 60L, TimeUnit.SECONDS, // keepAliveTime new ArrayBlockingQueue<>(100), // 队列 new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 );
2. 无界队列(LinkedBlockingQueue
)
- 使用场景:如果任务提交和处理的速度相对均衡,且我们不关心队列是否会过多积压任务,无界队列 也是一个常见的选择。
为什么使用:无界队列能够承接无限量的任务,避免了因任务队列大小限制而导致的拒绝或阻塞问题。在流量较大时可以避免线程池因队列满而拒绝任务。
- 优点:任务可以无限制地加入队列,线程池的核心线程池数和最大线程数不需要频繁调整,适应性较强。
- 缺点:如果任务提交速率过高,队列中的任务会持续增加,可能导致内存消耗过多,甚至出现 OutOfMemoryError。另外,线程池中的线程数也会不断增加,导致线程数过多时会有额外的上下文切换开销。
常见队列选择:
LinkedBlockingQueue
代码示例:
ExecutorService executorService = new ThreadPoolExecutor( 4, // corePoolSize 10, // maximumPoolSize 60L, TimeUnit.SECONDS, // keepAliveTime new LinkedBlockingQueue<>() // 无界队列 );
3. 同步队列(SynchronousQueue
)
- 使用场景:这种队列适用于需要快速处理每个任务的场景,通常任务处理时间较短且每个任务都需要独立的线程执行。
为什么使用:
SynchronousQueue
是一个不缓存任何任务的队列,它会直接将任务交给线程池中的线程来执行,如果没有线程空闲,提交任务的线程将被阻塞,直到有线程来处理任务。- 优点:没有任务积压,适合需要高并发且任务时间短的场景,每个任务都会被迅速处理。
- 缺点:没有缓存任务,可能导致频繁创建和销毁线程,影响性能。
常见队列选择:
SynchronousQueue
代码示例:
ExecutorService executorService = new ThreadPoolExecutor( 4, // corePoolSize 10, // maximumPoolSize 60L, TimeUnit.SECONDS, // keepAliveTime new SynchronousQueue<>() // 同步队列 );
总结:
- 有界队列(
ArrayBlockingQueue
):常用,因为它可以有效控制任务的数量,避免系统因为任务过多而崩溃。适用于任务量大且可控的场景。 - 无界队列(
LinkedBlockingQueue
):适合任务数目不确定且任务提交速率较低的情况,虽然它不会拒绝任务,但需要小心内存消耗。 - 同步队列(
SynchronousQueue
):适合极短时间、独立线程执行的任务场景,常用于高并发、需要快速响应的场景。
因此在手写线程池时,通常会选择 ArrayBlockingQueue
或 LinkedBlockingQueue
,具体根据任务的性质和系统的负载来决定:
- 如果任务提交量较大且能控制系统负载,通常选择
ArrayBlockingQueue
,它能避免系统崩溃。 - 如果任务不太频繁且可以容忍一些任务积压,使用
LinkedBlockingQueue
是一个不错的选择。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。