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

自定义的线程或者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完成不了,导致了问题的发生。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值