ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
排队有三种通用策略:
直接提交。工作队列的默认选项是 SynchronousQueue,
它将任务直接提交给线程而不保持它们。如果不存在可用于立即运行任务的线程,则试图把任务加入队列将失败,因此会构造一个新的线程。此策略可以避免在处理可能具有内部依赖性的请求集时出现锁。直接提交通常要求无界 maximumPoolSizes 以避免拒绝新提交的任务,此策
略允许无界线程具有增长的可能性。
无界队列。(不具有预定义容量的 LinkedBlockingQueue)将导致在所有 corePoolSize 线程都忙时新任务在队列中等待。这样,创建的线程就不会超过 corePoolSize。(因此,maximumPoolSize的值也就无效了。)当每个任务完全独立于其他任务,即任务执行互不影响时,适合于使用无界队列;例如,在 Web页服务器中。这种排队可用于处理瞬态突发请求,当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增长的可能性。
有界队列。当使用有限的 maximumPoolSizes时,有界队列(如 ArrayBlockingQueue)有助于防止资源耗尽,但是可能较难调整和控制。队列大小和最大池大小可能需要相互折衷:使用大型队列和小型池可以最大限度地降低 CPU 使用率、操作系统资源和上下文切换开销,但是可能导致人工降低吞吐量。如果任务频繁阻塞(例如,如果它们是 I/O边界),则系统可能为超过您许可的更多线程安排时间。使用小型队列通常要求较大的池大小,CPU使用率较高,但是可能遇到不可接受的调度开销,这样也会降低吞吐量
1.
ArrayBlockingQueue类
一个以数组为基础的有界阻塞队列,此队列按照先进先出原则对元素进行排序。队列头部元素是队列中存在时间最长的元素,队列尾部是存在时间最短的元素,新元素将会被插入到队列尾部。队列从头部开始获取元素。
ArrayBlockingQueue是“有界缓存区”模型的一种实现,一旦创建了这样的缓存区,就不能再改变缓冲区的大小。
ArrayBlockingQueue的一个特点是,必须在创建的时候指定队列的大小。当缓冲区已满,则需要阻塞新增的插入操作,同理,当缓冲区已空,需要阻塞新增的提取操作。
ArrayBlockingQueue是使用的是循环队列方法实现的,对ArrayBlockingQueue的相关操作的时间复杂度,可以参考循环队列进行分析
。
2
LinkedBlockingQueue
一种通过链表实现的阻塞队列,支持先进先出。队列的头部是队列中保持时间最长的元素,队列的尾部是保持时间最短的元素。新元
素插入队列的尾部。可选的容量设置可以有效防止队列过于扩张造成系统资源的过多消耗,如果不指定队列容量,队列默认使用
Integer.MAX_VALUE。LinkedBlockingQueue的特定是,支持无限(理论上)容量。
3
PriorityBlockingQueue
PriorityBlockingQueue是一种基于优先级进行排队的无界队列。队列中的元素按照其自然顺序进行排列,或者根据提供的Comparator进行排序,这与构造队列时,提供的参数有关。
使用提取方法时,队列将返回头部,具有最高优先级(或最低优先级,这与排序规则有关)的元素。如果多个元素具有相同的优先级,则同等优先级间的元素获取次序无特殊说明。
优先级队列使用的是一种可扩展的数组结构,一般可以认为这个队列是无界的。当需要新添加一个元素时,如果此时数组已经被填满,优先队列将会自动扩充当前数组(一般认为是,先分配一个原数组一定倍数空间的数组,之后将原数组中的元素拷贝到新分配的数组中,释放原数组的空间)。
如果使用优先级队列的iterator变量队列时,不保证遍历次序按照优先级大小进行。因为优先级队列使用的是堆结构。如果需要按照次序遍历需要使用Arrays.sort(pq.toArray())。关于堆结构的相关算法,请查考数据结构相关的书籍。
在PriorityBlockingQueue的实现过程中聚合了PriorityQueue的一个实例,并且优先队列的操作完全依赖与PriorityQueue的实现。
在PriorityQueue中使用了一个一维数组来存储相关的元素信息。一维数组使用最小堆算法进行元素添加。
4
DelayQueue
一个无界阻塞队列,只有在延时期满时才能从中提取元素。如果没有元素到达延时期,则没有头元素。
RejectedExecutionHandler
RejectedExecutionHandler接口提供了对于拒绝任务的处理的自定方法的机会。在ThreadPoolExecutor中已经默认包含了4中策略,因为源码
非常简单,这里直接贴出来。
CallerRunsPolicy:线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
这个策略显然不想放弃执行任务。但是由于池中已经没有任何资源了,那么就直接使用调用该execute的线程本身来执行。
AbortPolicy:处理程序遭到拒绝将抛出运行时RejectedExecutionException
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException();
}
DiscardPolicy:不能执行的任务将被删除
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
DiscardOldestPolicy:如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
该策略就稍微复杂一些,在pool没有关闭的前提下首先丢掉缓存在队列中的最早的任务,然后重新尝试运行该任务。这个策略需要适当小心。设想:如果其他线程都还在运行,那么新来任务踢掉旧任务,缓存在queue中,再来一个任务又会踢掉queue中最老任务。
分享到:
相关推荐
线程池的排队策略与BlockingQueue有关。 threadFactory:线程工厂,主要用来创建线程:默认值 DefaultThreadFactory; handler:表示当拒绝处理任务时的策略,就是上面提及的reject操作;有以下四种取值: ...
3. newFixedThreadPool:创建一个固定大小的线程池,线程数量保持不变,任务排队等待执行。 4. newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行。 5. ForkJoinPool:用于执行Fork/Join框架的...
线程池在现代多任务处理系统中扮演着至关重要的角色,尤其是在高并发的场景下,如Web服务器、电子邮件服务和数据库应用等。这些应用通常需要处理大量同时到来的请求,而每个请求都可能涉及复杂的计算或IO操作。如果...
- 任务调度:能够对任务进行排队,根据策略决定何时运行哪个任务。 - 提高性能:通过重用已存在的线程,减少了线程创建和销毁的开销。 - 可管理性:可以监控线程池的状态,动态调整线程池的大小,或者设置拒绝...
5. 管理策略:如果线程池满,新任务会被阻塞或根据特定策略排队等待;如果线程池中有空闲线程,任务将立即开始执行。 【Java线程池实现】 Java通过`java.util.concurrent`包提供了线程池的实现,如`...
- **线程管理**:线程池会根据预设策略调整线程数量,如达到最大线程数则排队等待,或当线程空闲超时后自动销毁。 4. **Linux线程实现**:在Linux中,线程由POSIX标准定义,使用`pthread_create()`函数创建线程,`...
- `corePoolSize`: 核心线程数,表示线程池中保持的最小线程数。 - `maximumPoolSize`: 最大线程数,定义了线程池允许的最大并发线程数。 - `keepAliveTime`: 当线程数量超过核心线程数时,空闲线程等待新任务的最长...
2. **任务调度**:线程池可以提供多种策略来处理新提交的任务,例如丢弃、拒绝或排队等待。 3. **重用线程**:避免了线程创建和销毁的开销,提高了系统的效率。 4. **性能优化**:线程池可以根据系统的负载动态调整...
线程池可以有效控制运行的线程数量,如果线程数量超过了最大数量,超出数量的线程排队等候;另一方面,如果线程数量低于最小数量,则空闲线程不会被销毁,以便重用。 #### 二、Java中的线程池接口 在Java中,...
4. **任务管理**:线程池可以按照一定的策略对任务进行排队,实现更加灵活的任务管理机制。 #### 三、C++线程池实现机制 在C++中,实现线程池通常有两种方式:手动实现和使用第三方库(如Boost.Thread或PPL)。 -...
如果提交的任务过多,超出线程池的处理能力,多余的请求会被排队等待,直到线程池中有空闲线程可用。 7. **线程优先级**: 线程池中的线程不支持设置优先级,所有线程池线程的优先级都是相同的。如果你的应用需要...
在 DynamicTp 项目中,线程池的配置可以通过配置文件来进行设置,例如线程池的大小、队列的大小、拒绝策略等。这些配置项可以根据实际情况进行调整,以满足不同应用场景的需求。 DynamicTp 项目提供了一个灵活的...
- 提供了线程池的配置选项,比如线程池的大小、任务排队策略等。 7. 线程池中线程的状态变化: - 新建(New):新创建的线程尚未启动。 - 可运行(Runnable):线程可能正在运行或者在运行队列中等待。 - 阻塞...
如果没有,线程池会根据预设的策略创建新的线程或将其放入队列等待。线程池通过自动调整线程数量来平衡系统负载和资源消耗,这使得应用程序更加高效且稳定。 `MainWindow.xaml.cs`可能是一个包含UI元素和事件处理的...
常见的拒绝策略有抛出异常、丢弃任务、排队等待等。 ### 如何优化线程池参数 1. **任务的性质**:要根据任务的类型和执行特性来调整线程池的参数。例如,对于CPU密集型任务,线程数接近CPU核心数时效率最优;而...
- 当线程池达到预设的最大线程数时,新的任务会被排队等待,直到有空闲线程可用。 - 如果线程池长时间没有任务,会自动回收空闲线程,以节省资源。 - 在适当的时候,线程池会根据系统负载和当前任务量动态调整工作...
3. **线程调度**:线程池中的线程调度策略,如公平调度、优先级调度等,确保任务得到合理分配。 4. **IOCP的使用**:提交I/O请求,接收完成通知,以及处理I/O结果。 5. **线程同步和通信**:线程间的同步机制,如...
线程池可以有效控制运行的线程数量,如果线程数量超过了最大数量,超出数量的线程排队等候。线程池不仅提高了程序的性能,还简化了多线程编程的复杂性。在Java中,`java.util.concurrent`包下的`ExecutorService`、`...
- maximumPoolSize:最大线程数,超过核心线程时,新提交的任务将排队等候。 - keepAliveTime:非核心线程在空闲时的存活时间。 - unit:存活时间的单位。 - workQueue:任务队列,用于存储等待执行的任务。 - ...
线程池的核心在于其任务调度策略,包括任务的提交、排队、分配以及线程的创建与销毁。鱼刺线程池在设计时考虑了性能优化,比如任务的优先级、线程的空闲超时等特性,使得资源利用率得到最大化。 拨号重试框架则是...