需求背景

一个非主要功能特殊时期的高并发问题。该场景用到了parallelStream并发流提高查询速度,但是Java8的并发流线程池默认是ForkJoinPool,是全局共享的,任何用到了并发流的业务操作默认都是一个线程池。

问题:所有parallelStream业务操作都使用一个线程池就有可能互相影响。比如帮助中心查询用户权限+内容过滤都用到了parallelStream,相当于这些操作都在一个池子里。在并发的时候就有可能互相影响。

特点:非主要功能且在特殊时间(平时不咋用、平时不会集中使用)

解决方案

特殊账号用户、普通用户在不同的线程池中

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@Test
void test() {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(i);
}

list.parallelStream().forEach((i) -> {
System.out.println(Thread.currentThread().getName() + "........XXX");
try {
Thread.sleep(500000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
});

}

@Test
void testPrivate() {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(i);
}
ForkJoinPool customThreadPool = new ForkJoinPool(4);
customThreadPool.submit(
() -> list.parallelStream().forEach((i) -> {
System.out.println(Thread.currentThread().getName() + "........XXX");
try {
Thread.sleep(50000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
// 自定义的ForkJoinPool不会使用主线程,所以需要主线程也sleep一下,方便查看控制台数据
try {
Thread.sleep(500000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

控制台输出:


默认线程池输出:image-20240610115344881

自定义线程池输出:image-20240610115356912


可以看到默认线程池是commonPool,自定义线程池是2,做到了同一个parallelStream线程池的隔离。

注意:parallelStream默认线程池主线程也参与工作,会看到main也会打印,但是自定义线程池则没有

补充

Java中的parallelStream:Java中的parallelStream

自定义parallelStream:自定义parallelStream的threadpool -阿里云开发者社区 (aliyun.com)