详解Java中的线程池

前言

本篇博客我将会详细地介绍什么是线程池及线程池的各种要点

一.线程池是什么

1.1概念

存放线程的池子,方便后续直接使用线程,而不是频繁地释放,降低开销。

1.2为什么要创建线程池

虽然创建销毁线程比创建销毁进程更轻量,但是频繁地创建销毁线程的时候还是比较低效的。

二.创建线程池的方法

创建线程池主要有两种方式:

1)通过Executors工厂类创建:

创建方式比较简单,但是定制能力比较有限

2)通过ThreadPoolExecutor创建:

创建方式比较复杂,但是定制能力强,LinkedlockingQueue表示线程池的任务队列,用户通过submit   /   execute向这个任务队列中添加任务,再由线程池中的工作线程来执行任务

三.ExecutorService和Executors

ExecutorService 表示一个线程池实例

Executors是一个工厂类,能够创建出几种不同风格的线程池

ExecutorService的submit方法能够向线程池中提交若干个任务

代码如下:

ExecutorService pool = Exectuors.newFixedThreadPool(10);
pool.submit(new Runnable() {
@Override
public void run(){
System.out.println("hello");
}
});

Executors 创建线程池的几种方式:

newFixedThreadPool: 创建固定线程数的线程池; newCachedThreadPool: 创建线程数⽬动态增⻓的线程池; newSingleThreadExecutor: 创建只包含单个线程的线程池; newScheduledThreadPool: 设定延迟时间后执⾏命令,或者定期执⾏命令. 是进阶版的 Timer. Executors 本质上是 ThreadPoolExecutor 类的封装。

四.ThreadPoolExecutor

ThreadPoolExecutor 提供了更多的可选参数,可以进一步细化线程池行为的设定

ThreadPoolExecutor的构造方法

※:理解ThreadPoolExecutor构造方法的参数

把创建一个线程池想象成开一个公司,每一个员工相当于一个线程;

1)corePoolSize: 正式员⼯的数量. (正式员⼯, ⼀旦录⽤, 永不辞退) 2)maximumPoolSize: 正式员⼯ + 临时⼯的数⽬. (临时⼯: ⼀段时间不⼲活, 就被辞退). 3)keepAliveTime: 临时⼯允许的空闲时间. 4)unit: keepaliveTime 的时间单位, 是秒, 分钟, 还是其他值. 5)workQueue: 传递任务的阻塞队列 6)threadFactory: 创建线程的⼯⼚, 参与具体的创建线程⼯作. 7)RejectedExecutionHandler: 拒绝策略, 如果任务量超出公司的负荷了接下来怎么处理?     

1.AbortPolicy(): 超过负荷, 直接抛出异常.

2.CallerRunsPolicy(): 调⽤者负责处理

3.DiscardOldestPolicy(): 丢弃队列中最⽼的任务.

4.DiscardPolicy(): 丢弃新来的任务

代码示例如下:

ExecutorService pool = new ThreadPoolExecutor(1, 2, 1000, TimeUnit.MILLISECONDS,
 new SynchronousQueue(),
 Executors.defaultThreadFactory(),
 new ThreadPoolExecutor.AbortPolicy)
for(int i=0;i<3;i++) {
 pool.submit(new Runnable() {
 @Override
 void run() {
 System.out.println("hello");
 }
 });
}

五.线程池工作流程

线程池形象例子如下图所示:

尾语

这篇博客到这里就结束啦,希望可以给大家带来帮助~~