我们使用了有界的队列,那么当队列满了之后如何处理后面进入的请求,我们可以通过不同的策略进行设置。
4种拒绝策略
接下来我们来创建一个容错率比较高的线程池。
public class WordTest {
public static void main(String[] args) throws InterruptedException {
System.out.println("开始执行");
// 阻塞队列容量声明为100个
ThreadPoolExecutor executorService = new ThreadPoolExecutor(10, 10,
0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(100));
// 设置拒绝策略
executorService.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 空闲队列存活时间
executorService.setKeepAliveTime(20, TimeUnit.SECONDS);
List<Integer> list = new ArrayList<>(2000);
try {
// 模拟200个请求
for (int i = 0; i < 200; i++) {
final int num = i;
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName() + "-结果:" + num);
list.add(num);
});
}
} finally {
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);
}
System.out.println("线程执行结束");
}
}
思路:我声明了100容量的阻塞队列,模拟了一个200的请求,很显然肯定有部分请求进入不了队列,但是我使用了CallerRunsPolicy策略,当队列满了之后,使用主线程去进行处理,这样就不会出现有部分请求得不到执行的情况,也不会因为因为阻塞队列过大导致内存溢出的情况。
通过测试200个请求全部得到执行,有3个请求由主线程进行了处理。
总结
如何更好的创建线程池上面已经说过了,关于线程池在业务中的使用,其实我们这种全局的思路是不太好的,因为如果从全局考虑去创建线程池,是很难把控的,因为你无法准确地评估所有的请求加起来会有多大的量,所以最好是每个业务创建独立的线程池进行处理,这样是很容易评估量化的。
另外创建的时候,最好评估下大概每秒的请求量有多少,然后来合理的初始化线程数和队列大小。
日拱一卒,功不唐捐
本文分享自微信公众号 - 一个程序员的成长(xiaozaibuluo)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。