用租车公司的方式打开java线程池,原理不再是问题
2020-08-25 本文已影响0人
小燃儿
线程的创建和销毁是比较费时的,所以我们会通过使用线程池来复用线程,降低资源消耗,提高响应。同时使用线程池可以避免无限制的创建线程,防止耗尽计算机资源。
(以下用租车为例,来模拟线程)
1.租车公司讲线程池
a. 如果你去一个远的地方,你就会需要一辆车。造一辆车耗费的资源可想而知,而到达目的地后,这辆车 对你又没有用了。
线程就像这辆车一样,不过它z在使用后,本着不浪费的原则系统就会销毁线程回收这一部分资源。
image
b. 而现实中我们也可以选择租车出行,出租车是属于出租车公司的,就如同线程池的线程。
- 由于出租车场地原因,最大汽车数量是一定的(最大线程数);
- 但是由于不同时间里,出行需求不同,不是所有的汽车都会用来出租,有些汽车公司会用来自己跑出租(而用来出租的就是核心线程数);
- 租车公司都会有预约机制,因此有预约排队的单子(工作队列);
- 预约额度满了之后就没有办法了,租车公司只能拒绝客户的预约了(拒绝策略);
以上与java线程池工作原理类似。对于线程池而言,内部的线程是可以复用的。而为了更好满足任务量会动态变大变小的需求,就引入了最大线程与工作队列。
image
2.Java线程池 ThreadPoolExecutor执行源码
我们现在来看看java中的线程池是怎么实现的吧。
// 构造函数,构建租车公司
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
corePoolSize: 核心线程池大小。
maximumPoolSize:最大线程池大小。可以认为是一个租车公司最大允许的造汽车数量
keepAliveTime:保活时间。就是指淡季的时候,那些多余的汽车(大于corePoolSize)在这个时间内,还没有人租赁的话就会用作其他用途,例如的士。
unit:保活时间单位。
workQueue:任务阻塞队列。可以想成是来预约租车的人,一般也是有限号。
threadFactory:线程工厂。就是指造汽车的工厂,一般可以用来命名汽车名等操作。
handler:拒绝策略。是指当租车公司所有的汽车都被租赁了,预约排队的人也满了。这个时候再有人来的时候公司只能直接拒绝操作了(java内置了4种策略)
// 执行任务,当有人来租车了:
public void execute(Runnable command) { // 用户需要用车做的任务
if (command == null)
throw new NullPointerException();
int c = ctl.get(); // 租车公司现在有的汽车数量
if (workerCountOf(c) < corePoolSize) { // 少于最低汽车数量要求
if (addWorker(command, true)) // 建造汽车,并执行用户任务
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) { // 确保公司还在运营 && 用户排队(发号)
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false)) // 排队人数满了,需要把用作他途的汽车拉回来出租了
reject(command); // 汽车也也用完了,需要拒绝当前来租车的人
}