多线程——Java线程池原理深入
来源:互联网 发布:windows loader win10 编辑:程序博客网 时间:2024/06/15 08:28
上次我们简单了解了一下什么是线程池以及Java中几种类型的线程池,今天我们来深入剖析一下线程池的原理。
1、构造
1. 线程池管理器(ThreadPoolManager):用于创建并管理线程池
2. 工作线程(WorkThread): 线程池中线程
3. 任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。
4. 任务队列:用于存放没有处理的任务。提供一种缓冲机制。
注:线程池管理器至少有下列功能:创建线程池,销毁线程池,添加新任务
2、线程状态
新建状态(New):新创建了一个线程对象。
就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
3、执行流程
a.一个任务提交,如果线程池大小没达到corePoolSize,则每次都启动一个worker也就是一个线程来立即执行
b.如果来不及执行,则把多余的线程放到workQueue,等待已启动的worker来循环执行
c.如果队列workQueue都放满了还没有执行,则在maximumPoolSize下面启动新的worker来循环执行workQueue
d.如果启动到maximumPoolSize还有任务进来,线程池已达到满负载,此时就执行任务拒绝RejectedExecutionHandler
// 流程就是:没达到corePoolSize,创建worker执行,达到corePoolSize加入workQueue// workQueue满了且在maximumPoolSize下,创建新worker,达到maximumPoolSize,执行rejectpublic void execute(Runnable command) { if (command == null) throw new NullPointerException(); // 1:poolSize达到corePoolSize,执行3把任务加入workQueue // 2:poolSize没达到,执行addIfUnderCorePoolSize()在corePoolSize内创建新worker立即执行任务 // 如果达到corePoolSize,则同上执行3 if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { // 3:workQueue满了,执行5 if (runState == RUNNING && workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) { // 4:如果线程池关闭,执行拒绝策略 // 如果poolSize==0,新启动一个线程执行队列内任务 ensureQueuedTaskHandled(command); } // 5:在maximumPoolSize内创建新worker立即执行任务 // 如果达到maximumPoolSize,执行6拒绝策略 } else if (!addIfUnderMaximumPoolSize(command)) // 6:拒绝策略 reject(command); // is shutdown or saturated }}
4、线程销毁
keepAliveTime:代表的就是线程空闲后多久后销毁,线程的销毁是通过worker的getTask()来实现的。
一般来说,Worker会循环获取getTask(),如果getTask()返回null则工作线程worker终结,那我们再看看什么时候getTask()返回null
Runnable getTask() { for (;;) { try { int state = runState; if (state > SHUTDOWN) return null; Runnable r; if (state == SHUTDOWN) // Help drain queue r = workQueue.poll(); else if (poolSize > corePoolSize || allowCoreThreadTimeOut) // 在poolSize大于corePoolSize或允许核心线程超时时 // 阻塞超时获取有可能获取到null,此时worker线程销毁 r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS); else r = workQueue.take(); if (r != null) return r; // 这里是是否运行worker线程销毁的判断 if (workerCanExit()) { if (runState >= SHUTDOWN) // STOP或TERMINATED状态,终止空闲worker interruptIdleWorkers(); return null; // 这里返回null,代表工作线程worker销毁 } // 其他:retry,继续循环 } catch (InterruptedException ie) { // On interruption, re-check runState } }}
5、线程池关闭
平缓关闭 shutdown:这个方法会将runState置为SHUTDOWN,会终止所有空闲的线程,同时不再接受新的任务,而仍在工作的线程不受影响,所以队列中的任务人会被执行
立即关闭 shutdownNow:此方法将runState置为STOP,和shutdown方法的区别是,这个方法会终止所有的线程(取消所有正在执行和未执行的任务),所以队列中的任务也不会被执行了。
总结:
通过这次学习,我们不仅知道了线程池是如何管理线程,而且还了解了线程多种状态之间的转换,这样更加便于我们对线程池的理解。之后,我们还将继续学习关于多线程的知识,让我们每天都有成长。
- 多线程——Java线程池原理深入
- Java线程池原理(多线程)
- Java 多线程线程池 - 线程池原理
- Java 多线程线程池 - 线程池原理
- Java多线程之线程池深入分析
- java技术深入(一)——java多线程(六)——线程池
- Java 多线程9:线程池实现原理
- Java多线程--线程池的原理分析
- Java 并发编程深入学习——线程池及其实现原理
- Java 多线程线程池 - 线程池原理(1)
- Java 多线程线程池 - 线程池原理(2)
- Java多线程线程池(3)--线程池原理
- 深入理解java线程池—ThreadPoolExecutor
- 深入理解java线程池—ThreadPoolExecutor
- 深入理解java线程池—ThreadPoolExecutor
- 深入理解java线程池—ThreadPoolExecutor
- 深入理解java线程池—ThreadPoolExecutor
- java技术深入(一)——java多线程(二)——线程中断
- sql server语句总结之日期格式
- WildFly(JBoss)创建虚拟目录
- tigase的客户端测试工具spark
- http的幂等性
- Jmeter 和LoadRunner 的区别
- 多线程——Java线程池原理深入
- InnoDB关键特性之刷新邻接页-异步IO
- HDU-5724-组合博弈
- Red and Black(dfs水题)
- 互斥锁标记synchronized
- 查找--二叉查找树分析与实现
- sql
- 4. Apache配置
- java面试题:输出旋转数组的最小元素(剑指offer)