抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

思维导图

文章已收录Github精选,欢迎Starhttps://github.com/yehongzhi/learningSummary

前言

在实际开发场景中,我们经常要使用多线程开发应用,比如实现异步操作,或者为了提高程序的效率等等。但是以前我见过有实习生在使用的时候是直接new Runable(),然后start()。没有使用线程池,可能很多初学者对线程池在多线程开发中没有足够的认识,所以我写一篇文章讲讲线程池,希望对大家有所启发。

一、什么是线程池

线程池借鉴了”池化”技术的思想,线程池能够对线程的生命周期进行管理,对线程重复利用,并且能够以一种简单的方式将任务的提交与执行相解耦。

举个例子来说,线程就像是某个公司的客服小姐姐,每天都要接很多客户的电话,如果同时有1000个客户打电话进来咨询,按正常的逻辑,那就需要1000个客服小姐姐,但是在现实中往往需要考虑成本问题,招这么多人费用太多了,于是就可以这样优化,可以招100个人成立一个客服中心,如果同时超过100个人则提示让客户等待,等有空闲的客服小姐姐时就去响应客户。实现效益最大化。这就是一个池化技术在现实生活中类似的例子。

二、为什么使用线程池

一种技术的出现,肯定是要解决存在的问题。如果不用线程池,会怎么样呢?很简单,需要时创建线程,线程跑完销毁,如果频繁去做这两个动作,就会造成比较大的资源消耗。所以线程池主要就是解决这个问题。

因此在《java并发编程的艺术》书中就提到以下几点:

  • 降低资源消耗。通过重复使用已创建的线程,降低线程创建和销毁造成的资源消耗。
  • 提高响应速度。当有任务到达时,任务可以不需要的等到线程创建就能立即执行。
  • 提高线程的可管理性。使用线程池可以进行统一的分配,调优和监控。

三、Executor

创建线程池主要使用ThreadPoolExecutor这个类,所以我们先看一张类图。

一般来说,遵守面向接口编程的思想,我们都喜欢使用ExecutorService接口接收线程池实例。如下:

1
2
3
4
public static void main(String[] args) throws Exception {
//创建线程池
ExecutorService executor = new ThreadPoolExecutor(10, 10, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10));
}

这里可以看到创建线程池是使用ThreadPoolExecutor构造器来创建。构造器的参数有什么意义呢,继续往下看。

3.1 七个关键参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* corePoolSize 核心线程数
* maximumPoolSize 最大线程数
* keepAliveTime 线程存活时间
* unit keepAliveTime的时间单位,有日,小时,分钟,秒等等