• -------------------------------------------------------------
  • ====================================

使用线程池newFixedThreadPool时注意队列过大造成阻塞而引起锁不释放的问题

技能 dewbay 2年前 (2022-01-12) 1688次浏览 已收录 0个评论 扫描二维码

自定义的线程或者newFixedThreadPool()使用 LinkedBlockingQueue 作为任务队列的需要注意

案列 1:

有两处业务 共用了一把锁

lock.writeLock().lock();
try{
while(true){
//clean data
}
}finally{
lock.writeLock().lock();
}

从这里看出,因为长时间持有 lock,那么其它线程肯定会阻塞。

lock.readLock.lock();
try{
// check
}finally{
lock.readLock.unlock();
}

请求来的时候,这里会 check 一些参数,这个地方会拿 lock,这么看

清理逻辑,会阻塞住请求过来的业务
发送端出现了超时的问题
所有为什么发送方会出现了超时。

找到线程池,发现所有的请求都会经过一个线程池。疑问:线程池满了,业务方占用了线程池,于是导致发送方请求处理 不了,超时,这时候就要去找日志,看是否有 RejectedException().发现没有日志。

查看线程池的实现,

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}

LinkedBlockingQueue 知道 队列大小 Integer.MAX_VALUE,导致请求都会阻塞到 queue 里面了
综上问题:

锁的粒度过大,长时间占用锁。
所有业务都用同一个线程池,应该分成多个业务线程池,关键业务分开。防止所有任务都被阻塞
在这 记录下 曾经遇到的 对 ThreadPoolExecutor 的 不正当使用 导致死锁的问题

案列 2:

private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(2,100,2L,TimeUnit.MINUTES,new LinkedBlockingQueue<>(),new ThreadFactory(){
private AtomicInteger id = new AtomicInteger(0);
@Override
public Thread newThread(Runable r){
Thread thread = new Thread();
thread.setName(“core_service”+id.addAndGet(1));
return thread;
}
},new ThreadPoolExecutor.CallerRunPolicy());
public static void main(String[] args)throws Exception{
Future<Long> f1 = (Future<Long>) executor.submit(()->{
Thread.sleep(1000);
Future<Long> f3 = (Future<Long>) executor.submit(()->return -1L);
System.out.println(“f1,f3″+f3.get());
return -1L;
});
Future<Long> f2 = (Future<Long>) executor.submit(()->{
Thread.sleep(1000);
Future<Long> f4 = (Future<Long>) executor.submit(()->return -1L);
System.out.println(“f2,f4″+f4.get());
return -1L;
});
System.out.println(“here”);
System.out.println(“f1″+f1.get());
System.out.println(“f2″+f2.get());
}

结果 :here

线程阻塞了,无法得到 f1,f2

原因:当使用 LinkedBlockingQueue 不指定大小的话,maxmumPoolsize 此配置将无效。因为当线程数量达到 coreSize 时,会放入队列等待,队列是无界的,导致线程数量达到 core 就不会增长。

so:线程执行 f1 占用一个线程,延迟到 f2 也占用一个线程,此时 执行 f3 提交到队列中执行,一直等待执行没有返回,导致 f2 完成不了,导致了问题的发生。


露水湾 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:使用线程池newFixedThreadPool时注意队列过大造成阻塞而引起锁不释放的问题
喜欢 (2)
[]
分享 (0)
关于作者:
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址