java多线程:线程池原理、阻塞队列


一、线程池定义和使用

jdk 1.5 之后就引入了线程池。

1.1 定义

从上面的空间切换看得出来,线程是稀缺资源,它的创建与销毁是一个相对偏重且耗资源的操作,而Java线程依赖于内核线程,创建线程需要进行操作系统状态切换。为避免资源过度消耗需要设法重用线程执行多个任务。线程池就是一个线程缓存,负责对线程进行统一分配、调优与监控。(数据库连接池也是一样的道理)

什么时候使用线程池?

单个任务处理时间比较短;需要处理的任务数量很大。

线程池优势?

重用存在的线程,减少线程创建、消亡的开销,提高性能、提高响应速度。

当任务到达时,任务可以不需要等到线程创建就能立即执行。

提高线程的可管理性,可统一分配,调优和监控。

1.2 线程池在 jdk 已有的实现

在 juc 包下,有一个接口:Executor :

Executor 又有两个子接口:ExecutorService 和 ScheduledExecutorService,常用的接口是 ExecutorService。

同时常用的线程池的工具类叫 Executors。

例如:

ExecutorService service = Executors.newCachedThreadPool();

Executor 框架虽然提供了如 newFixedThreadPool()、newSingleThreadExecutor()、newCachedThreadPool()、newScheduledThreadPool() 等创建线程池的方法,但都有其局限性,不够灵活。

上面的几种方式点进去会发现,都是用 ThreadPoolExecutor 进行创建的:

newSingleThreadExecutor 字面意思简单线程执行器

java多线程:线程池原理、阻塞队列

2. newFixedThreadPool 字面意思**固定的线程池**,传参就是线程固定数目,适用于执行长期任务的场景。

java多线程:线程池原理、阻塞队列

3. newCachedThreadPool 字面意思**缓存线程池**,核心线程0,最大线程非常大,动态创建的特点。

java多线程:线程池原理、阻塞队列

4. newScheduledThreadPool 字面意思**时间安排线程池**,指定核心线程数。

java多线程:线程池原理、阻塞队列

java多线程:线程池原理、阻塞队列

5. newSingleThreadScheduledExecutor 字面意思**单线程安排执行器**,也就是基于只有一个核心线程的执行器之外,又可以扩展。其中又用 DelegatedExecutorService 委托执行器服务进行了包装。

java多线程:线程池原理、阻塞队列

可以看到,上面直接用 Executors 工具类默认的一些实现 new 出来的线程池都是用的 ThreadPoolExecutor 线程执行器这个类进行构造的,不过参数不同,导致了效果的侧重点不同。

因此,自己创建线程池推荐的方法就是,直接使用 ThreadPoolExecutor 进行个性化的创建:

java多线程:线程池原理、阻塞队列

构造方法种的参数有 7 个:

corePoolSize:线程池维护线程的最少数量 (core : 核心

maximumPoolSize:线程池维护线程的最大数量,显然必须>=1

keepAliveTime:线程池维护的多余的线程所允许的空闲时间,最长可以空闲多久,时间到了,如果超过 corePoolSize 的线程一直空闲,他们就会被销毁。

unit:线程池维护线程所允许的空闲时间的单位

workQueue:线程池所使用的缓冲队列,已经提交但是没有执行的任务会放进这里

threadFactory:生成线程池种工作线程的线程工厂,一般使用默认

handler:线程池对拒绝任务的处理策略,当队列满且工作线程已经达到maximumPoolSize。

阿里的 java 开发手册,强制要求,通过 ThreadPoolExecutor 来自定义,不能使用内置的,避免资源耗尽。这个很好理解,1 的类型就只有一个核心线程和最大现场,2 没有扩展性,3、4、5的最大线程数太大,内存会爆炸。

1.3 线程池使用方法

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzjwdd.html