JDK线程池原理剖析

这篇文章不打算讲解什么是线程池?线程池怎么用?直接讲解原理

1、线程池关键参数解释

JDK 线程池的实现类是 ThreadPoolExecutor,构造函数关键参数解释如下:

corePoolSize 核心线程,线程池维持的线程数量,即使没有任务执行也会维持这个数量不变,除非设置了 allowCoreThreadTimeOut 这个参数为 true

maximumPoolSize 线程池中允许创建线程的最大数量

keepAliveTime 非核心线程的空闲等待时间,超过这个时间将被销毁

unit 针对keepAliveTime 参数的时间单位

workQueue 任务队列

2、 execute和submit的区别?

1)submit有返回值

2)submit提交的线程类型,会被jdk包装成一个FutureTask

3、运行原理

3.1任务执行流程

这不是一个流程图,是为了说明线程启动到执行任务的大概流程

3.2 源码分析

先说下执行主流程,再细看源码。

执行流程:execute(Runnable command) >>addWorker(Runnable firstTask, boolean core)>>runWorker(Worker w)

源码分析:

1)execute(Runnable command)方法

  该方法会调用addWorker(Runnable firstTask, boolean core)方法执行任务

2)addWorker(Runnable firstTask, boolean core) 方法

该方法代码比较长,我们看下关键的代码部分

既然启动线程了,那我们就去Worker里看看

3) Worker 内部类

既然2)中调用了start()方法,那么必然会调用Worker的 run()方法

接下来看 runWorker(this)方法,最最关键的部分就在这里,老办法,我们也还是看最关键的代码片段

4)看下这个方法 processWorkerExit(Worker w, boolean completedAbruptly)

总结一下,线程池就是维护一个线程集合,用这些线程来反复的执行任务,这些线程分为核心线程和非核心线程,核心线程一般不会被销毁,就算是没有任务也会空闲等待(除了设置 allowCoreThreadTimeOut参数),非核心线程,当空闲等待时间到达设置的参数范围,就会被销毁回收。比较难理解的是JDK是如何维护线程集合并执行任务?这里在说一下,线程池初始化,当第一个任务来的时候,线程池会创建一个线程并将该线程存入一个线程集合,刚才的任务作为该线程的第一个任务执行,执行完该任务,此时线程不会立即结束,会通过getTask()方法,以阻塞等待方式从任务队列里面获取任务执行,因此如果阻塞队列有任务,就取出任务执行,如果队列没有任务,就阻塞等待任务,所以正常情况下,该线程会一直存活。当第二个任务来了以后,会执行和第一个任务同样的动作,以此类推,直到核心线程数量达到corePoolSize设置的参数数量,这样就形成了线程集合,也就是线程池。当任务很多的时候,核心线程不能及时全部处理完毕,此时线程池就会将任务存入任务队列,如果队列满了,并且 maximumPoolSize 大于 corePoolSize,就会创建非核心线程执行任务。

原文地址:https://www.cnblogs.com/tspeking/p/9298067.html

时间: 2024-08-29 08:48:37

JDK线程池原理剖析的相关文章

线程池原理剖析

---恢复内容开始--- 前面的我那几个源码截图,大家可以自己点进去看看,共同点都是封装了 ThreadPoolExcutor这构造函数 无非就是传递的参数不一样~~ 比如 SingleThreadExecutor public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, Tim

java并发包&线程池原理分析&锁的深度化

      java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问.数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中.当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制.移动.代价比较高.因此,它适合随机查找和遍历,不适合插入和删除. 2.Vector与Arra

Java并发——线程池原理

"池"技术对我们来说是非常熟悉的一个概念,它的引入是为了在某些场景下提高系统某些关键节点性能,最典型的例子就是数据库连接池,JDBC是一种服务供应接口(SPI),具体的数据库连接实现类由不同厂商实现,数据库连接的建立和销毁都是很耗时耗资源的操作,为了查询数据库中某条记录,最原始的一个过程是建立连接.发送查询语句.返回查询结果.销毁连接,假如仅仅是一个很简单的查询语句,那么可能建立连接与销毁连接两个步骤就已经占所有资源时间消耗的绝大部分,如此低下的效率显然让人无法接受.针对这个过程是否能

线程池原理

在面向对象编程中,对象创建和销毁是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收.所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是对一些很耗资源的对象创建和销毁.如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些"池化资源"技术产生的原因.比如大家所熟悉的数据库连接池就是遵循这一思想而产生的,下面将介绍的线程池技术同样符合这一思想. 多线程技术主要解决处

Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理

相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理 以下是本文的目录大纲: 一.shutdown()  --  温柔的终止线程池 interruptIdleWorkers()  --  中断空闲worker tryTerminate()  --  尝试终止线程池 二.shutdown

java多线程系类:JUC线程池:03之线程池原理(二)(转)

概要 在前面一章"Java多线程系列--"JUC线程池"02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代码(基于JDK1.7.0_40)线程池源码分析(一) 创建"线程池"(二) 添加任务到"线程池"(三) 关闭"线程池" 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509954.h

线程池原理和简单实现

1.线程池原理 :伪代码 在线程池中假设最多开3个线程,当小于三个,进行创建,添加到集合中,然后不停的轮训线程集合进行执行,直到为空时,进入等待状态 public class ThreadPool { int maxCount = 3;//假设最多开只能开三个线程 AtomicInteger count =new AtomicInteger(0);// 当前开的线程数 count=0,为了线程同步,使用此api LinkedList<Runnable> runnables = new Link

线程池;java实现线程池原理

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中.如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙.如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值.超过最大值的线程可以排队,但他们要等到其他线程完成后才启动. 组成部分 1.线程池

jdk线程池主要原理

本文转自:http://blog.csdn.net/linchengzhi/article/details/7567397 正常创建一个线程的时候,我们是这样的:new thread(Runnable实现类).这里,thread是线程,Runnable实现类是业务逻辑,这样线程和业务逻辑紧紧绑定在一起. 采用线程池来处理的时候,我们动态生成若干个线程存于池中,但是这些线程要执行那些业务逻辑是不知道的,由于业务逻辑个数和具体的逻辑需要用户来指定,这些是变化的,我们需要自己编写并存于linkedLi