34WorkerThread模式

正确地创建线程池

  • 使用有界队列
  • 指明拒绝策略
  • 业务相关的名字

线程死锁的场景

现象:应用每运行一段时间偶尔就会处于无响应的状态,监控数据看上去一切都正常,但是实际上已经不能正常工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//L1、L2两阶段任务共用一个线程池
ExecutorService es = Executors.
newFixedThreadPool(2);
//L1阶段的闭锁
CountDownLatch l1=new CountDownLatch(2);
for (int i=0; i<2; i++){
System.out.println("L1");
//执行L1阶段任务
es.execute(()->{
//L2阶段的闭锁
CountDownLatch l2=new CountDownLatch(2);
//执行L2阶段子任务
for (int j=0; j<2; j++){
es.execute(()->{
System.out.println("L2");
l2.countDown();
});
}
//等待L2阶段任务执行完
l2.await();
l1.countDown();
});
}
//等着L1阶段任务执行完
l1.await();
System.out.println("end");

两个线程全部都阻塞在 l2.await();没有空闲的线程执行L2阶段的任务了.
解决办法:不同阶段任务使用不同线程池

提交到相同线程池中的任务一定是相互独立的,否则就一定要慎重

总结

  • 正确创建线程池
    使用有界队列
    指明拒绝策略
    业务相关的名字
  • 避免死锁
  • ThreadLocal内存泄露问题
  • 异常处理