线程池拒绝策略不当导致的伪死锁

从别的同事那里接手了一个保存kafka数据到hbase的程序,交接时候同事就提示我程序有时候会由于hbase挂了容易导致程序出现死锁,让后期维护时候多看看这个程序状态,根据日志找到offset,重新配置消费重启程序即可,当时也没多想就直接接下来了。

维护一段时间之后发现有时候hbase集群有问题了恢复之后程序还能正常执行,有时候就不能正常执行,产生同事说的死锁情况,程序不再执行,出现这种情况的频率几乎1个月1-2次。

结合jstck线程状态我发现是一种伪死锁,之所以叫伪死锁是因为程序设计过程中没有自定义加锁操作,所以通过jstack分析线程状态并未找到死锁,但是程序就是不再执行了,所有线程都在waiting状态,具体线程状态如下:

对应的提交任务处代码如下:

第一个jstack图可以发现线程池里的5号线程在执行addQueue操作,4号线程在等待分配任务,还有个Thread-7在拒绝策略执行后也执行addQueue操作。

根据上述两幅图以及源代码发现程序逻辑如下:程序有别的线程将kafka数据往queue里写数据,thread-7将queue的数据提交给线程池执行,线程池一共有5个线程,最大线程数量也是5,线程池的任务队列大小设置为了1000,saveHTable操作将数据写到hbase不同的表中,此时有个表异常了,当写数据出异常时候再通过addQueue操作将数据加回到队列中,由于hbase异常无法写数据,任务队列很快就满了,此时由于最大线程数和线程池初始线程数一致所以直接执行拒绝策略,该线程池配置的拒绝策略是由提交任务的线程也就是thread-7运行线程池中的task,由于hbase有异常,所以所有写异常表的task都会失败,会将数据提交到queue中,queue很快就会满了,由于此时已经没有线程给线程池提交任务了,所以就会出现jstack图中的部分线程在等待task部分线程在addQueue,thread-7也在addQueue,queue又是满的,此时thread-7也在执行异常表的保存失败之后的addQueue操作,至此这个程序的queue只有生产者没有消费者了,所以程序不在执行了,产生伪死锁现象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值