专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 深入探究线程池的工作原理

深入探究线程池的工作原理

更新时间:2020-11-16 17:32:34 来源:动力节点 浏览1388次

我们在工作中或多或少都使用过线程池,但是为什么要使用线程池呢?从他的名字中我们就应该知道,线程池使用了一种池化技术,和很多其他池化技术一样,都是为了更高效的利用资源,例如链接池,内存池等等。那么,线程池的工作原理到底是怎样的呢?


实际上,线程池是一种生产者 - 消费者模式,线程池的使用方是生产者,线程池本身是消费者。我们可以通过下面的代码来理解线程池的工作原理。

public class ThreadPoolDemo {

//利用阻塞队列实现生产者-消费者模式

BlockingQueueworkQueue;

//保存内部工作线程

Listthreads = new ArrayList<>();

private ThreadPoolDemo(int poolSize, BlockingQueueworkQueue) {

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 {

BlockingQueueworkQueue =

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,

BlockingQueueworkQueue) {

this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,

Executors.defaultThreadFactory(), defaultHandler);

}

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueueworkQueue,

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方法提交任务,线程池根据当前运行状态和特定参数对任务进处理,整体模型如下图:

image.png


在 ThreadPoolDemo 的内部,维护了一个阻塞队列 workQueue 和一组工作线程,工作线程的个数由构造函数中的 poolSize 来指定。用户通过调用 execute() 方法来提交 Runnable 任务,execute() 方法的内部实现仅仅是将任务加入到 workQueue 中。ThreadPoolDemo 内部维护的工作线程会消费 workQueue 中的任务并执行任务,相关的代码就是代码中的 while 循环。


以上就是对线程池的工作原理的探究,就整个线程池工作原理而言,其中最重要的还是线程池的饱和策略,用户通过实现RejectedExecutionHandler接口自定义饱和策略,并通过ThreadPoolExecutor多参的构造函数传入。也许你看完了本文,对线程池的工作原理理解的还不够透彻,那么请观看本站的多线程教程吧,让你全面掌握多线程相关知识!


提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>