更新时间:2020-11-16 17:32:34 来源:极悦 浏览1485次
我们在工作中或多或少都使用过线程池,但是为什么要使用线程池呢?从他的名字中我们就应该知道,线程池使用了一种池化技术,和很多其他池化技术一样,都是为了更高效的利用资源,例如链接池,内存池等等。那么,线程池的工作原理到底是怎样的呢?
实际上,线程池是一种生产者 - 消费者模式,线程池的使用方是生产者,线程池本身是消费者。我们可以通过下面的代码来理解线程池的工作原理。
public class ThreadPoolDemo {
//利用阻塞队列实现生产者-消费者模式
BlockingQueue
//保存内部工作线程
List
private ThreadPoolDemo(int poolSize, BlockingQueue
this.workQueue = workQueue;
// 创建工作线程
for (int idx = 0; idx < poolSize; idx++) {
WorkerThread work = new WorkerThread();
work.start();
threads.add(work);
}
}
// 提交任务
public void execute(Runnable command) throws InterruptedException {
workQueue.put(command);
}
// 工作线程负责消费任务,并执行任务
class WorkerThread extends Thread {
public void run() {
//循环取任务并执行
while (true) {
Runnable task = null;
try {
task = workQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
assert task != null;
task.run();
}
}
}
public static void main(String[] args) throws InterruptedException {
BlockingQueue
new LinkedBlockingQueue<>(2);
// 创建线程池
ThreadPoolDemo pool = new ThreadPoolDemo(10, workQueue);
// 提交任务
pool.execute(()->{
System.out.println("hello world");
});
}
}
通过上面的Demo可见,线程池的创建都是通过ThreadPoolExecutor完成的,来看一下它的构造方法。
# -> ThreadPoolExecutor构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
...
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
构造方法声明的一系列参数非常重要,理解了它们线程池的基本原理你就掌握了,我们来看看他们的具体含义:
corePoolSize 核心线程数,除非设置核心线程超时(allowCoreThreadTimeOut),线程一直存活在线程池中,即使线程处于空闲状态。
maximumPoolSize 线程池中允许存在的最大线程数。
workQueue 工作队列,当核心线程都处于繁忙状态时,将任务提交到工作队列中。如果工作队列也超过了容量,会去尝试创建一个非核心线程执行任务。
keepAliveTime 非核心线程处理空闲状态的最长时间,超过该值线程则会被回收。
threadFactory 线程工厂类,用于创建线程。
RejectedExecutionHandler 工作队列饱和策略,比如丢弃、抛出异常等。
线程池创建完成后,可通过execute方法提交任务,线程池根据当前运行状态和特定参数对任务进处理,整体模型如下图:
在 ThreadPoolDemo 的内部,维护了一个阻塞队列 workQueue 和一组工作线程,工作线程的个数由构造函数中的 poolSize 来指定。用户通过调用 execute() 方法来提交 Runnable 任务,execute() 方法的内部实现仅仅是将任务加入到 workQueue 中。ThreadPoolDemo 内部维护的工作线程会消费 workQueue 中的任务并执行任务,相关的代码就是代码中的 while 循环。
以上就是对线程池的工作原理的探究,就整个线程池工作原理而言,其中最重要的还是线程池的饱和策略,用户通过实现RejectedExecutionHandler接口自定义饱和策略,并通过ThreadPoolExecutor多参的构造函数传入。也许你看完了本文,对线程池的工作原理理解的还不够透彻,那么请观看本站的多线程教程吧,让你全面掌握多线程相关知识!
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习