降低资源消耗 。通过重复利用已创建的线程降低线程创建和销毁造成的消耗(主要) 。
提高响应速度 。当任务到达时 , 任务可以不需要等到线程创建就能立即执行 。
提高线程的可管理性 。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性 。
Java提供四种线程池创建方式:
- newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程 , 若无可回收 , 则新建线程 。
- newFixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待 。
- newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行 。
- newSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行 。
public class ThreadPoolExecutor extends AbstractExecutorService
public abstract class AbstractExecutorService implements ExecutorService

文章插图
2.2 ThreadPoolExecutor介绍
实际项目中,用的最多的就是ThreadPoolExecutor这个类,而《阿里巴巴Java开发手册》中强制线程池不允许使用Executors去创建,而是通过New ThreadPoolExecutor实例的方式 , 这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险 。

文章插图
我们从ThreadPoolExecutor入手多线程创建方式,先看一下线程池创建的最全参数 。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException;
if (workQueue == || threadFactory == || handler == )
throw new PointerException;
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
参数说明如下:
- corePoolSize:线程池的核心线程数,即便线程池里没有任何任务,也会有corePoolSize个线程在候着等任务 。
- maximumPoolSize:最大线程数,不管提交多少任务,线程池里最多工作线程数就是maximumPoolSize 。
- keepAliveTime:线程的存活时间 。当线程池里的线程数大于corePoolSize时 , 如果等了keepAliveTime时长还没有任务可执行 , 则线程退出 。
- Unit:这个用来指定keepAliveTime的单位,比如秒:TimeUnit.SECONDS 。
- BlockingQueue:一个阻塞队列,提交的任务将会被放到这个队列里 。
- threadFactory:线程工厂,用来创建线程,主要是为了给线程起名字,默认工厂的线程名字:pool-1-thread-3 。
- handler:拒绝策略 , 当线程池里线程被耗尽,且队列也满了的时候会调用 。
对于BlockingQueue个人感觉还需要单独拿出来说一下 。
BlockingQueue:阻塞队列,有先进先出(注重公平性)和先进后出(注重时效性)两种 , 常见的有两种阻塞队列:ArrayBlockingQueue和LinkedBlockingQueue
队列的数据结构大致如图:

文章插图
队列一端进入,一端输出 。而当队列满时,阻塞 。BlockingQueue核心方法:1. 放入数据put2. 获取数据take 。常见的两种Queue:
2.2.2 ArrayBlockingQueue
基于数组实现,在ArrayBlockingQueue内部,维护了一个定长数组,以便缓存队列中的数据对象 , 这是一个常用的阻塞队列,除了一个定长数组外,ArrayBlockingQueue内部还保存着两个整形变量,分别标识着队列的头部和尾部在数组中的位置 。
一段代码来验证一下:
package map;
import java.util.concurrent.*;
public class MyTestMap {
// 定义阻塞队列大小
private static final int maxSize = 5;
public static void main(String[] args){
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(maxSize);
推荐阅读
- iphone14技术规格
- 进程和线程:你了解它们的区别吗英语
- 阳光玫瑰葡萄大棚怎么建,阳光玫瑰葡萄种植技术与管理
- 荷兰豆种植 荷兰豆种植技术与管理
- 手机格式化照片用技术手段还会被恢复吗
- 蜜蜂怎么养殖 蜜蜂怎么养殖技术视频
- 物联网应用技术属于什么专业类别
- 现代式短跑技术强调的是什么跑法
- 蛋鸡养殖技术 蛋鸡养殖技术培训
- 物联网应用技术是什么
