多线程分工模式--Thread-Per-Message模式

从名字可以看出,为每一个任务或者消息分配一个线程,适用于类似httpServer的场景,为每一个请求分配一个线程去执行。但是在java中创建线程的成本比较高(线程创建耗时且线程占用的内存较大)有俩种取代方案

  1. 用线程池取代,利用线程的复用思想
  2. 用更轻量的线程方案取代,golang中的协程,java中loom中的Fiber

注:多线程分工模式下这个应该是最简单的方案了

java中的另一个模式WorkThread模式

java创建线程、以及线程切换的开销很重,所以我们可以采用workThread模式即用线程池,来复用线程。

workthrea的“坑”

由于线程池中的任务有相互依赖关系,导致线程池因为没有资源被死锁,见下面:

  1. 开辟线程池
  2. 避免线程池的共享
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
27
//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 阶段任务执行完
// for循环俩个线程都会在l2.await()时候阻塞住,因为线程池只有2个l1 l2共享线程池且有关联,所以没有资源了
l2.await();
l1.countDown();
});
}
// 等着 L1 阶段任务执行完
l1.await();
System.out.println("end");