Java并发编程线程池的实现原理分析以及Executors工具快速的创造各种线程池

这是我参与8月更文挑战的第12天,活动详情查看: 8月更文挑战

实现原理

在上篇文章中,已经讲解了如何去使用一个线程池,当我们向线程池提交一个任务后,线程池会怎样处理这个任务呢,接下来让我们一起来解读线程池的相关工作原理。
通过方法入口:execute 查看,execute()只有不到20行的代码, 在方法体内,源码也写了对应的注释,英文注释翻译过来大体意思就是:当我们线程提交给线程池后,线程池会进行3个步骤判断

  1. 线程池判断核心线程里的线程是否都在执行任务,如果不是,则创建一个新的工作线程来执行任务,如果线程池里的核心线程都在执行任务,则进入第二步判断
  2. 判断线程池的工作队列是否已经满,如果工作队列没有满,则将新提交的任务存储到工作队列中,如果工作队列已满,则进入第三步判断
  3. 判断线程池的线程是否都处于工作状态,如果没有则创建一个新的工作线程来执行任务如果已经满了,则执行饱和策略来执行我们提交的任务

未命名文件 (2).png
具体源码如下:

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);
复制代码

可以将刚刚文字描述的内容画成对应的流程图,线程池的处理流程图如下

线程池处理流程图.png

工作机制

在线程池中,我们只需要将整个任务提交给线程池,而不是创建线程来执行,线程池在拿到任务后,就会在内部协调空闲的线程池来执行我们提交的任务,待任务执行完成后,在执行其他的任务。一个线程只能够执行一个任务,但是我们可以提交多个任务到线程池,线程池无空闲的线程执行,会将我们的任务缓存到队列中。
线程池跟线程一样,也有不同的状态,线程池分为5个状态:RUNNING,SHUTDOWN,STOP,TIDYING,TERMINATED

  • **RUNNING:**线程池被创建出来的时候就处于Running状态,等待任务执行,在这个时候可以接受新任务,并且对已接收的任务会正常处理
  • **SHUTDOWN:**关闭线程池,又分为两种关闭方式:shutdown()及shutdownNow(),这两种区别是:
    • shutdown:不接受新任务,但是对已添加的任务会继续执行,等已有任务执行完成后,才会关闭线程池
    • shutdownNow:不接受新任务。对已添加的任务不会继续执行,直接关闭线程池
  • **STOP:**不接收新任务,不处理已添加的任务,并且会中断正在处理的任务
  • **TIDYING:**所有的任务已终止,队列中的任务数量为0,线程池会变为TIDYING状态,会执行钩子函数terminated()
  • **TERMINATED:**线程池处在TIDYING状态时,执行完terminated()之后,就会由关闭整个线程池,因为在最终关闭之前会调用钩子函数:terminated(),这个时候我们就可以重载方法terminated来实现在线程池关闭之前释放我们自定义的资源。

未命名文件.png

Executors工具

newFixedThreadPool    

创建固定线程数的线程池,适用于为了满足资源管理的需求,需要限制当前线程数量的应用场景

newSingleThreadExecutor

创建只有一个线程的线程池,适用于需要保证顺序执行各个任务,并且不会存在多线程执行任务的场景

newCachedThreadPool

创建无界的线程池,适用于执行很多短期的异步任务

newScheduledThreadPool

创建定时执行的线程池,可用于定时任务

对于线程池的使用场景比较普遍,合理的使用线程池,可以降低资源消耗,减少线程不停的创建与销毁造成的消耗,可以重复利用已有的线程来执行任务,也可以提交我们应用的响应速度,通过创建多个任务并行运行提高任务的并发量,提高运行的速度;使用线程池也可以对线程任务的管控,不会造成无限制的创建资源,这样会不停的消耗系统的资源,降低系统的稳定性,我们也可以通过线程池提供的方法来监控内部的运行情况。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享