Glassfish 3服务器线程池队列满及16线程等同一锁问题求助
嘿,这个问题我之前在GlassFish 3上踩过类似的坑,咱们一步步来拆解解决:
问题核心拆解
首先你遇到的两个现象是强关联的:
- 报错
java.util.concurrent.RejectedExecutionException: The thread pool's task queue is full, limit: 256:说明EJB线程池(从线程名__ejb-thread-pool1能明确)的任务队列已经顶到上限256,新的请求任务直接被拒绝了。 - 16个线程卡在同一个锁上,比如你贴的线程片段:
"__ejb-thread-pool1" daemon prio=6 tid=0x39657c00 nid=0x1c08 waiting on condition [0x3297f000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x117b2cb0> (a jav...
本质原因是:这16个线程都在等待同一个共享资源的锁,导致它们无法释放回线程池,可用线程越来越少,后续任务只能堆积在队列里,最终撑爆队列抛出异常。
具体解决步骤
1. 先定位锁对应的核心资源
从线程转储里的<0x117b2cb0>这个内存地址,你可以用这些方式找到对应的对象:
- 用VisualVM、jhat这类工具加载线程转储文件,解析这个地址对应的对象类型和实例信息;
- 多次抓取线程转储,找有没有线程状态为
BLOCKED或者RUNNABLE且明确持有<0x117b2cb0>锁的线程——这个线程就是“瓶颈点”,它拿着锁不释放,导致所有其他线程堵死。
常见的锁资源场景:数据库连接、Singleton EJB、自定义业务锁、第三方资源连接(比如消息队列、缓存)。
2. 临时缓解:调整EJB线程池配置
先救急,避免服务持续报错:
- 登录GlassFish管理控制台(默认地址
http://localhost:4848); - 导航到 配置 -> 线程池 -> __ejb-thread-pool1;
- 调整这几个关键参数:
- 增大
队列大小(Queue Size):比如从默认256调到512或更高,先给任务更多缓冲空间; - 调整
核心线程数(Core Pool Size)和最大线程数(Maximum Pool Size):如果是IO密集型业务(比如大量数据库查询、远程调用),可以适当增大线程数;如果是CPU密集型,别超过CPU核心数的2倍。
- 增大
3. 根本解决:修复锁竞争问题
这才是解决问题的核心,分场景处理:
- 如果是数据库连接锁:检查是否有长事务未提交、数据库连接未及时关闭;可以给连接池配置超时时间,或者优化SQL查询、减少事务持有时间;
- 如果是Singleton EJB锁:GlassFish中Singleton默认是
@Lock(LockType.WRITE),所有调用都会排队。如果是只读操作,改成@Lock(LockType.READ);如果是读写混合,拆分Singleton的职责,把读写逻辑分离,减少锁粒度; - 如果是自定义业务锁:检查锁的粒度是不是太粗(比如锁了整个对象而非具体属性),或者有没有死循环、长时间操作持有锁的情况;尽量用细粒度锁,或者用并发容器替代自定义锁;
- 如果是第三方资源锁:检查第三方服务的响应时间,是否有超时未处理的请求,考虑增加资源连接数或者配置超时重试机制。
临时应急操作
如果当前服务已经卡死无响应,先重启GlassFish恢复服务,但这只是临时方案,必须跟进上面的根本优化,否则问题会重复出现。
内容的提问来源于stack exchange,提问作者jmann
相关产品推荐
相关产品推荐

