关于线程池

131 阅读3分钟

啥是线程池?

所谓线程池, 其实就是对线程的一种资源管理. (对就是这么短因为我吹不下去)

为什么要使用线程池

在有多个任务逐步提交的情况下, 如果按照平常的模式用for循环, 每一个任务就new 一个线程去执行, 完毕之后再去销毁, 这样在任务数极其多的情况下是非常消耗CPU和内存的, 为了避免这种情况, 我们一般会使用线程池. 去感性地理解, 就是线程在执行任务完结之后并不会不会销毁而是去继续去执行下一个任务 . 所以性能就提高了.

线程池是如何使用的?

一般来说,最通俗的做法就是自定义一个任务类实现Runnable接口, 然后在run方法里面写任务方法, 然后把这个类放在 线程池的execute方法就可以了. 但是这种做法有个弊端, 就是任务方法和线程绑死了.

当然还有更聪明的做法(以下是个人想法):

1.自定义一个任务接口 在里面定义一个任务执行方法, 假设接口名为ITask , 方法名为 executeTask.

图片.png

2.定义一个任务父类, 实现这个接口 , 方法体不写任何内容

图片.png

3.去定义各种不同的任务子类, 继承这个任务父类, 方法体内写上各自不一样的任务.

图片.png

图片.png

4.定义一个线程类实现Runnable接口, 定义一个属性Task, 在其构造器中传入这个Task的子类来实现不同的任务

图片.png

这样就完全实现了任务方法跟线程类分开了

图片.png

关于线程池的参数介绍

对于 new 一个线程池 , 当中会传递各种不一样的参数 .

图片.png

corePoolSize : 核心线程数

核心线程数指的是该线程池可执行线程任务的数量, 以corePoolSize为标准 ,例如corePoolSize为5, 那么线程池里面可同时执行的线程任务数为5, 特别注意的一点, 假设线程池这个时候有4个线程是空闲的, 此时有新任务提交, 线程池会新开一条线程来执行此任务,而不是从空闲的线程中随便拿一条线程来执行任务. 也就是说如果corePoolSize未满的情况下, 宁愿新开一条线程也不会用已有线程去执行提交的任务.

workQueue : 线程队列

假设线程池的corePoolSize已满, 这个时候如果有新任务提交, 而且也没有空闲线程来处理, 就会放入线程队列里面等待被执行. 说白了就是放入等待区, 而等待区的空间就是这个线程队列.

有三种最常见的队列类型 : 直接交接 : SynchronousQueue 无界队列 : LinkedBlockingQueue 有界队列 : ArrayBlockingQueue

maximumPoolSize : 最大线程数

如果corePoolSize 和 队列已满, 这个时候再有新任务提交, 那么就会额外地增加一个线程, 但是增加的线程数也会有一个上限, 这个上限就是maximumPoolSize

keepAliveTime : 线程的存活时间

如果当前的线程数多余corePoolSize, 那么多余的线程空闲时间超过keepAliveTime, 它们就会被终止.

关于线程池的参数解析

头三个是最重要的参数, 涉及到添加线程的规则

1 如果线程数小于corePoolSize, 即使其他线程处于空闲,也会创建一个新线程来执行任务.

2 如果线程数等于或大于 corePoolSize 但少于 maxPoolSize , 则将任务放入队列里面.

3 如果队列已满,并且线程数小于maxPoolSize, 则创建一个新线程来运行任务.

4 如果队列已满, 并且线程数大于或等于 maxPoolSize 则拒绝任务.

图片.png