Java 5.0 就开始自带线程池的实现,其中固定大小的线程池,对普通使用还是很好用的。就是 Executors.newFixedThreadPool ,指需要指定一个大小数目就可以。相对于其他几种方式,易于实现高效稳定的服务器。
但是好用归好用,一些需要非常细心的问题,还是需要关注的,尤其是高并发场景,7*24不间断运行场景下。本文就是把这些地方记录下来,在设计和实现时,在这些问题上务必不能马虎,因为这关系到稳定性和效率,且不易通过测试来排查。
(1)实现:
几种线程池,都是通过 ThreadPoolExecutor 来实现的,如下:
- ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler)
newFixedThreadPool :
public static ExecutorService newFixedThreadPool(int paramInt) { return new ThreadPoolExecutor(paramInt, paramInt, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); }
而 LinkedBlockingQueue的实现:
public LinkedBlockingQueue() { this(2147483647); }
这个默认的构造函数,实际上是有一些问题的(实际是构造了一个大小为 Integer.MAX_VALUE的任务队列)。
(2)问题
我们设想一个场景,客户端/服务器工作模式,请求来得很快,服务器端accept之后,将Socket放到了任务队列中,读请求处理,并发送响应。客户端连接来得很快,但处理没有那么快(例如需要IO或大量数学运算),所以来了之后就都排在队列里。一直到2147483647。
但是实际上,如果一个新的任务排在第100甚至1000、10000,客户端都可以等待,但是如果排到了 1000,000,客户端还会等待着吗?就像你如果去银行办业务,眼看排队都排到街上了,今天肯定轮不到了,你还会继续等吗?
换成计算机的设计语言,客户端连接,按照约定俗成,都是有超时的,开始提交了请求自然会等待,一定时间内得不到响应就超时进入异常处理流程了,那么,服务器队列里那个Socket还有什么意义呢?
(3)结论
所以说,在设计时,队列的长度是一定要用心设计和考虑的,除了在Demo和简单测试一下的程序里,不要轻易而简单的使用newFixedThreadPool ,要想清楚它的问题,在使用时使用其它方式避免。
一般情况下,队列的大小遵循下面的公事:
queSize <= ClientTimeOut(秒) * TPS
队列大小 小于等于 客户端超时 * 每秒处理的交易数
当然,这些数据都是估算,另外,也取决于你做的东西,对于客户端超时早就走了,服务器端还得处理这种情况是一种什么态度和需求。
相关推荐
Java线程池是一种高效管理并发任务执行的机制,它通过维护一组可重用的线程来减少创建和销毁线程的开销。线程池在Java中由`java.util.concurrent`包下的`ExecutorService`接口及其实现类,尤其是`ThreadPoolExecutor...
Java线程池是Java并发编程中的重要组成部分,它在Java 5及后续版本中引入,大大简化了线程管理和资源调度。线程池通过`Executor`接口和`ExecutorService`接口提供了一套强大的机制,允许开发者高效地创建、管理和...
在实际开发中,我们可以通过监控线程池的状态,如队列的长度、活动线程数等,来评估线程池的效率并进行相应的调整。此外,通过分析线程池的源码,可以帮助我们深入理解其内部工作机制,以便在遇到性能问题时能更精准...
### Java线程池常用方法详解 #### 一、引言 自Java 5引入并发包`java.util.concurrent`以来,线程的管理与控制变得更为高效与便捷。在这个包中,`Executor`框架成为了线程管理和调度的核心。通过`Executor`,我们...
3. **最大线程数** = (每秒最多任务数 - 队列长度) / 单线程秒执行任务数。 #### 七、代码示例 下面是一个简单的自定义线程池的示例代码: ```java import java.util.concurrent.*; public class ...
7. **监控与管理**:可以根据需要实现监控和管理机制,例如监控线程池的负载、任务队列的长度,以及根据需要调整线程池的参数。 通过这样的C++线程池实现,开发者能够在C++程序中享受到与Java线程池类似的便利性和...
标题中的“Spring线程池”指的是Spring框架中提供的线程池实现,它是Spring对Java的...同时,结合日志和监控工具,我们可以实时查看线程池的状态,包括当前线程数、活跃线程数、任务队列长度等,以便于诊断和解决问题。
3. **队列最大长度** (`queueCapacity`): 当提交的任务数量超过核心线程数时,超出的任务会被放入等待队列。这里设置为200,意味着当线程数达到核心线程数后,最多还能接受200个任务进入队列。 4. **空闲线程存活...
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。这种线程池非常适合执行一些短暂的异步任务,因为它可以自动地对线程进行管理和回收。示例...
4. 监控与日志:添加监控机制,记录线程池的运行状态,如当前线程数、队列长度等,便于分析和优化。同时,记录线程池中的异常和关键操作日志,便于问题排查。 5. 线程优先级:根据任务的重要性和紧急程度,可以考虑...
- **固定长度队列**:如使用`ArrayBlockingQueue`创建固定长度的队列,可以限制同时执行的任务数量,有助于避免因任务过多而导致的系统负载过高。 - **无界队列**:如使用`LinkedBlockingQueue`创建无界队列,可以...
当线程池达到其最大容量时,新请求的任务不会立即执行,而是被放入队列等待,直到有线程可用。 线程池中的队列处理策略主要有两种:一是拒绝服务,即当线程池满时,直接拒绝新的任务请求;二是等待队列,新任务会被...
1. **ArrayBlockingQueue**:基于数组实现的有界阻塞队列,队列长度是固定的,遵循先进先出(FIFO)原则。它提供了公平锁和非公平锁的选择,公平锁保证了等待最久的线程优先获得锁。 2. **LinkedBlockingQueue**:...
JAVA 创建线程池的注意事项 ...例如,可以使用 ThreadPoolExecutor 的 AbortPolicy 来避免线程池的队列长度达到 Integer.MAX_VALUE。 创建线程池需要注意以上几点,以避免出现不必要的错误和资源耗尽的风险。
线程池通常会维护一个任务队列,新任务将被加入到这个队列中排队,当线程池中的线程空闲下来,就从队列中取出任务进行执行。这样,即使资源有限,系统也可以有效地管理资源,保证任务不会丢失,同时避免了频繁地创建...
9. **线程池的监控与调优**:实时监控线程池的状态,如当前线程数、队列长度、拒绝任务数量等,以便进行性能调优。 10. **异常处理**:线程池需要处理任务执行过程中的异常,例如通过设置异常处理器,确保线程池在...
1. 创建线程池:开发者根据需求配置线程池的大小、队列长度等参数。 2. 提交任务:应用将任务提交给线程池,线程池将其放入任务队列。 3. 分配任务:线程池中的空闲线程会从任务队列中取出任务并执行。 4. 任务执行...
9. **监控与诊断**:为了确保线程池的健康运行,开发者通常需要监控线程池的状态,如当前活动线程数、已完成任务数、队列长度等。 10. **异常处理**:线程池会捕获并处理执行任务过程中发生的异常,确保线程池的...