b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

Java线程池的执行原理分析

电脑杂谈  发布时间:2020-05-10 01:13:52  来源:网络整理

java 线程池_java线程池执行原理_java线程池原理

本文将分析线程池程池生命周期内执行任务的过程.

线程池状态

首先识别通过线程池代码运行的两个参数:

runState: 线程池的运行状态

workerCount: 工作线程数

线程池使用32位int来保存runState和workerCount. 高3位是runState,其余29位是workerCount. 该代码将重复使用runStateOf和workerCountOf来获取runState和workerCount.

运行中: 可以接收新任务并可以执行等待队列中的任务

关闭: 无法接收新任务,并且可以执行等待队列中的任务

停止: 无法接收新任务,无法在等待队列中执行任务,并尝试终止所有正在运行的任务

整理: 所有任务已终止,执行终止()

终止: 终止()已完成

默认情况下,线程池的状态开始从RUNNING流动到TERMINATED状态的末尾. 不需要遍历中间的每个状态,但是无法返回该状态. 以下是状态更改的可能路径和条件:

图1线程池状态更改路径

java线程池执行原理_java 线程池_java线程池原理

创造工人

线程池负责根据Worker类执行任务. Worker继承了AbstractQueuedSynchronizer,这导致Java并发框架的核心AQS.

AbstractQueuedSynchronizer,称为AQS,是Java并发包中一系列同步工具的基本实现. 原理是根据状态位控制线程的入队阻塞和出队,以处理同步.

AQS不会在这里开始讨论,只需要知道Worker包装了Thread,它将执行任务即可.

调用execute将根据线程池的情况创建一个工作程序,可以将其总结为以下四种情况:

图2线程池中工作者的四种可能性

标记1对应第一种情况. 需要注意的是,addWorker传递了core,core = true是corePoolSize,core = false是maximumPoolSize,它需要检查workerCount是否超过添加时允许的最大值.

标记2对应于第二种情况,检查线程池是否正在运行,并将任务添加到等待队列中. 标记3再次检查线程池的状态. 如果线程池突然处于非运行状态,请删除刚刚添加到等待队列中的任务,并将其移交给RejectedExecutionHandler. 标记4发现没有工作程序,然后首先添加一个空任务工作程序.

标记5对应于第三种情况,正在等待的队列无法再添加任务,请调用addWorker以添加一个来处理.

标记6对应于第四种情况. addWorker的核心传入false,并且调用失败,表明workerCount已超出maximumPoolSize,然后由RejectedExecutionHandler处理.

java线程池执行原理_java线程池原理_java 线程池

标记1的第一段代码,目的很简单,就是向workerCount添加一个. 至于为什么这么长时间编写代码,是因为线程池的状态不断变化,并且需要在并发环境中保证变量的同步. 外循环确定线程池状态,任务不为空,队列也不为空. 内部循环使用CAS机制来确保workerCount正确增加. 如果您不了解CAS,则可以看到无阻塞同步机制CAS. 随后增加和减少workerCount将使用CAS.

标签2的第二段代码相对简单. 创建一个新的Worker对象,并将Worker添加到worker中(Set集合). 成功添加后,在worker中启动线程. 最后,确定线程是否成功启动,如果失败,则直接调用addWorkerFailed.

addWorkerFailed将减少已增加的workerCount,并调用tryTerminate结束线程池.

工作执行力

Worker使用ThreadFactory在构造函数中创建Thread,并在run方法中调用runWorker,这似乎是实际执行任务的地方.

标签1进入循环,并从getTask获取要执行的任务,直到它返回null. 在这里达到了线程重用的效果,使线程可以处理多个任务.

标记2是更复杂的判断,它确保线程池在STOP状态下被中断,并且线程在非STOP状态下不被中断.

标记3调用run方法,并且该任务实际上已执行. 在执行前后提供了两种方法beforeExecute和afterExecute,它们由子类实现.

标记4中的completedTasks计算工作人员已执行的任务数量,最后将其添加到completedTaskCount变量中. 您可以调用相应的方法以返回一些统计信息.

标签5的变量CompleteAbruptly指示工人是否异常终止. 在这里执行意味着正常执行. 后续方法需要此变量.

标记6在调用processWorkerExit时结束,稍后将进行分析.

java线程池原理_java线程池执行原理_java 线程池

让我们看一下用于工作者从等待队列中获取任务的getTask方法:

标记1检查线程池的状态java线程池执行原理,这是SHUTDOWN和STOP之间的区别. 如果线程池处于SHUTDOWN状态,则将首先处理等待队列中的任务;否则,线程将处于等待状态. 如果它处于STOP状态,则将不再处理等待队列中的任务.

标记2首先查看变量allowCoreThreadTimeOut. 如果为false,则该工人处于空闲状态并且不会结束;如果为true,则工作线程的空闲时间大于keepAliveTime时,它将结束. 这之后是一个非常复杂的判断,因此很难将其转换为文本描述. 你自己看. 请注意,wc> maximumPoolSize,这可能是由于在运行时调用setMaximumPoolSize和wc> 1引起的. 当等待队列不为空时,至少保留一个工作线程.

标记3是从等待队列中提取任务的逻辑. 根据时间,它分为等待keepAliveTime或阻塞直到有任务.

最后看一下结束工作者所需执行的操作:

在正常情况下java线程池执行原理,getTask中的workerCount将减少一. Mark 1使用变量completedAbruptly来确定工人是否异常退出. 如果是这样,则需要在workerCount上添加一个减号.

标签2将工作人员处理任务的数量添加到总数中,并将其从工作人员集中删除.

标签3尝试终止线程池,稍后将对此进行研究.

当标记4处理线程池仍处于RUNNING或SHUTDOWN状态时,如果worker异常结束,它将直接添加worker. 如果allowCoreThreadTimeOut = true并且等待队列中有任务,请至少保留一个工作线程;如果allowCoreThreadTimeOut = false,则workerCount不小于corePoolSize.

摘要worker: 线程池启动后,将在该线程中创建该worker,包装提交的Runnable任务并执行它,在执行后等待下一个任务,并在不再需要它时结束.

关闭线程池

关闭线程池不是问题. 工人在泳池中处于不同的状态. 在实际释放线程池之前,必须安排工作程序的“未来”. ThreadPoolExecutor提供了两种方法来关闭线程池:

java 线程池_java线程池原理_java线程池执行原理

关机: 无法再提交任何任务,提交的任务可以继续运行;

shutdownNow: 无法提交更多任务. 已提交但尚未执行的任务无法运行. 正在运行的任务可以继续运行,但是会被中断并返回已提交但尚未执行的任务.

shutdown将线程池切换到SHUTDOWN状态,并调用interruptIdleWorkers中断所有空闲的worker,最后调用tryTerminate尝试结束线程池.

ShutdownNow与关闭类似,线程池切换到STOP状态,并且中断目标是所有工作程序. 排水队列将在等待队列中返回未执行的任务.

interruptIdleWorkers和interruptWorkers的实现原理都是遍历工作人员集合并满足中断条件的工作人员.

上面的代码似乎多次调用tryTerminate. 这是一种尝试将线程池切换到TERMINATED状态的方法.

标签1检查线程池的状态. 在以下情况下,不需要后续操作,只需直接返回即可.

正在运行(仍在运行,无法停止)

正在整理或终止(没有工作人员在运行)

关闭并等待队列为非空(执行后停止)

当工作线程不为空​​时,标记2调用interruptIdleWorkers. 您可能想知道为什么在关机期间调用它. 为什么再次调用它,一次只中断一个空闲的工作程序?您需要知道,当工作进程关闭时,该工作进程可能正在执行队列中阻塞的获取操作. 如果您不知道要结束,则必须添加interruptIdleWorkers. 每次只有一个因processWorkerExit而中断时,tryTerminate也将被执行以自动中断下一个空闲工作器.

标记3是最终状态开关. 线程池将首先进入TIDYING状态,然后进入TERMINATED状态. 终止的空方法提供给子类实现.

在调用关闭线程池方法之后,您需要等待线程池切换到TERMINATED状态. awaitTermination检查线程池是否在限定时间内进入TERMINATED状态,代码如下:

后记

已经审查了线程池的主要逻辑,并且线程池的总体设计非常清晰. 如果有错误或不足,欢迎您指出,并欢迎您留言. 这次介绍了线程池的生命周期. 在下一篇文章中,我们将研究精细控制任务的生命周期,即提交和将来.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/ruanjian/article-204652-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 成公张茂
        成公张茂

        人家做生意上来先给你个大金戒指

      • 李东丽
        李东丽

        剩我买块电池么

      • 杨俊
        杨俊

        不再意淫伊拉克

      每日福利