线程池的设计与原理解析(四)之---runWorker()方法

news2024/9/29 17:37:41

在调用start()方法,调用的就是worker的run方法,实际上调用的是runWorker()方法

  public void run() {
            // 这个是核心方法,worker启动后的逻辑从这里进入
            runWorker(this);
        }

在这里插入图片描述
简单的梳理runWorker的流程

  • 如果构造worker的时候,指定了firstTask,那么首先执行firstTask。否则从队列中获取任务;
  • Worker线程会循环的getTask(),然后去执行任务
  • 如果getTask()为空,那么worker线程就会退出
  • 在任务执行前后,可以自定义扩展beforeExecute与afterExecuter方法
  • 如果检测到先吃池为STOP状态,并且线程还没有被中断过的话,进行中断处理

1.将初始执行task赋值给task

 Runnable task = w.firstTask;

2.completedAbruptly:是否是突然退出; false 正常退出; 默认ture

  boolean completedAbruptly = true;

3.条件判断

// 条件1: 指的是firstTask 不为 null.
// 条件2: 说明当前线程在queue中获取任务成功. 如果返回null。
// getTask是一个会阻塞线程的方法。说明当前线程需要执行退出逻辑
 (task != null || (task = getTask()) != null)   
   // w 就是启动worker
    final void runWorker(Worker w) {
        // wt == w.thread。
        Thread wt = Thread.currentThread();
        // 将初始 执行 task 赋值给 task
        Runnable task = w.firstTask;
        // 清空当前 w.firstTask引用
        w.firstTask = null;
        // 为了初始化worker 的 state == 0 和 exclusiveOwnerThread == null
        w.unlock(); // allow interrupts

        // 是否是突然退出 ; false 正常退出
        boolean completedAbruptly = true;
        try {
            // 条件1: 指的是firstTask 不为 null.
            // 条件2: 说明当前线程在queue中获取任务成功. 如果返回null。
            // getTask是一个会阻塞线程的方法。说明当前线程需要执行退出逻辑
            while (task != null || (task = getTask()) != null) {

                // worker加锁设置,为当前线程
                // 为什么要设置独占锁? shutdown时会判断当前worker状态,根据独占锁是否空闲来判断当前worker是否正在工作
                w.lock();
                // If pool is stopping, ensure thread is interrupted;
                // if not, ensure thread is not interrupted.  This
                // requires a recheck in second case to deal with
                // shutdownNow race while clearing interrupt

                // 条件1: 说明线程池目前处于 STOP/TIDYING.TERMINATION 此时线程一定要给它一个中断信号
                // 条件2: 前部分成立:说明当前线程池状态是>=STOP 且当前线程未设置中断状态;
                // 后半部分:
                // 强制刷新当前线程的中断标记 false, 有可能上一个task时,业务代码里面将当前线程的中断标记位设置为了true,且没有处理。
                // 这里一定要强制刷新一下,不会影响到后面的task
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())

                    //
                    wt.interrupt();
                try {
                    // 钩子方法,留给子类实现
                    beforeExecute(wt, task);
                    // 表现异常情况,如果thrown不为空,表示 task运行过程中,向上层抛出异常了
                    Throwable thrown = null;
                    try {
                        // task 可能是 FutureTask 也可能是Runnable接口实现类
                        task.run();
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    w.completedTasks++;

                    // worker处理完成一个任务后,会释放独占锁。然后再次到queue队列中获取任务
                    w.unlock();
                }
            }
            // 什么情况执行到这里?
            // 1. getTask() 返回null。 说明当前线程应该执行退出
            // 2.
            completedAbruptly = false;
        } finally {
            // task.run() 抛出异常,直接到这里
            // 正常退出 completedAbruptly 为false
            // 异常退出 completedAbruptly 为 true
            processWorkerExit(w, completedAbruptly);
        }
    }

总结:runWorker
1.如果task不为空,则开始执行task方法
2.如果task为空,则通过getTask()再去取任务,并赋值给task,如果取到的Runnable不为空,则执行该任务;
3.执行完毕后,通过while循环继续getTask()取任务
4.如果getTask()取到的任务依然是空,那么整个runWorker()方法执行完毕;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/96523.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LinuxOS-IO-动静态库

文章目录AMC的了解动静态库1.理论理解2.如何制作一个库??了解实验:制作库交给别人使用生成静态库生成文件 删除文件 发布文件使用静态库?生成动态库使用动态库AMC的了解 Access:文件最近被访问的时间。 我们发现实际操作下来,文…

谁在「元宇宙」里卖咖啡?

作者 | 曾响铃 文 | 响铃说 全球首个全场景数实融合的「世界杯元宇宙」音乐盛典,已经落下了帷幕。 在14日与16日举办的两场动感地带世界杯音乐盛典中,既能看到周杰伦、李宇春、G.E.M。邓紫棋、周深等乐坛大咖,又能看到动感地带数智代言人橙…

字节跳动首发485道Java岗面试题(含答案)

就目前国内的面试模式来讲,在面试前积极的准备面试,复习整个 Java 知识体系将变得非常重要,可以很负责任地说一句,复习准备的是否充分,将直接影响你入职的成功率。 但很多小伙伴却苦于没有合适的资料来回顾整个 Java …

docker搭建gitlab 服务器

1、搜索gitlab镜像 # 查找Gitlab镜像 docker search gitlab # 拉取Gitlab镜像 docker pull gitlab/gitlab-ce:latest 2、启动Gitlab容器 docker run \-itd \-p 9000:80 \-p 9022:22 \-v /home/gitlab/etc:/etc/gitlab \-v /home/gitlab/logs:/var/log/gitlab \-v /home/gi…

drupal远程代码执行 (CVE-2018-7600)漏洞学习与复现

文章目录一、漏洞描述二、POC&EXP一、漏洞描述 drupal是一个开源PHP管理系统,架构使用的是php环境mysql数据库的环境配置。在Drupal 6.x,7.x,8.x系列的版本中,均存在远程代码执行漏洞。该漏洞产生的原因在于Drupal对表单渲染…

ADI Blackfin DSP处理器-BF533的开发详解58:DSP控制ADXL345三轴加速度传感器的应用(含源码)

硬件准备 ADSP-EDU-BF533:BF533开发板 AD-HP530ICE:ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 MEMS三轴加速度传感器 我做了一个三轴加速度传感器的子卡,插在这个板子上,然后写了一些有意思的应用程序。 硬件实现原理…

Nacos2.2版本发布了,我为其贡献了几行代码并适配了PostgreSQL插件

目录 一、背景 二、个人贡献 三、Nacos使用适配的PostgreSQL插件 3.1、插件源码工程项目结构: 3.2、打包加载插件 3.3、修改配置文件为PostgreSQL连接字符串 3.4、导入数据库脚本文件 四、总结 一、背景 Nacos 是 Dynamic Naming and Configuration-Servic…

计算机毕设Python+Vue心灵治愈服务平台(程序+LW+部署)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

C++那些事之高效率开发C++/C

1.神器 目前开发C/C用的比较多的当属Vim、VS code、CLion。 Vim配上插件编写C/C效率高的不少。 VSCode配上自定义配置及快捷键、vim插件效率跟vim旗鼓相当。 CLion因其独特的CMakeLists.txt管理方式及强大的代码补全等功能,编写本地代码绝对好于前两者。 但是对…

什么是数据指标体系?

定义 对当前业务有参考价值的统计数据 作用 监控业务情况 通过拆解指标寻找当前业务问题 评估业务可改进的地方,找出下一步工作的方向 常用数据指标 谁:用户数据 干了什么:行为数据 结果怎样:业务数据 选好数据指标的通用…

大数据学习:学生排序

文章目录一、提出任务二、任务过程(一)准备数据1、在虚拟机上创建文本文件2、上传文件到HDFS指定目录(二)实现步骤1、创建Maven项目2、添加相关依赖3、创建日志属性文件4、创建学生实体类5、创建学生映射器类5、创建学生归并器类6…

Python变量类型教程

变量存储在内存中的值。这就意味着在创建变量时会在内存中开辟一个空间。 基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存中。 因此,变量可以指定不同的数据类型,这些变量可以存储整数,小…

Springboot跨域处理的几种方式

作者简介 作者名:编程界小明哥 简介:CSDN博客专家,从事软件开发多年,精通Java、JavaScript,博主也是从零开始一步步把学习成长、深知学习和积累的重要性,喜欢跟广大ADC一起打野升级,欢迎您关注&…

基于springboot+mybatis的制造行业供应链管理系统

一、项目简介 基于springbootmybatis的制造行业供应链管理系统 二、实现功能 支持基础数据、用户管理、职务管理、修改密码、客户账号管理、组织管理 物料管理、物料短码、物料短码查询、物料分类维护 项目类别维护、分配采购员、设置最大最小库存、物料检验项管理 部门管…

Elasticsearch入门、API操作

文章目录概念倒排索引es的一些概念安装ES、Kibana总结索引库操作mapping映射属性创建索引库和映射查询索引库修改索引库删除索引库总结文档操作新增文档查询文档删除文档修改文档全量修改增量修改RestAPI引入依赖、初始化RestClient索引库 操作创建索引库删除索引库判断索引库是…

[附源码]Python计算机毕业设计黑河学院校友交流网站Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等…

ABBYY2023PDF及OCR文字识别软件

ABBYY FineReader PDF2023最新版使专业人士在数字化工作场所能够更大限度地提高效率。 FineReader PDF 的特色是采用了 ABBYY 新推出的基于 AI的OCR 技术,可以更轻松地在同一工作流程中对各种文档进行数字化、检索、编辑、加密、共享和协作。 现在,信息工…

U盘安装CentOS7

官网找到CentOS7的ISO镜像:CentOS-7-x86_64-DVD-2207-02.iso(大小4.42G) 准备一个8G的U盘,格式化,然后通过UltraISO工具将ISO镜像写入到U盘。 接着开机启动U盘,华硕是按esc键。 选择install cenetos7 li…

【图像处理】打靶仿真系统【含GUI Matlab源码 1043期】

⛄一、打靶仿真系统简介 1 课题描述 2 课题建模过程 a)第一,获取武器的各个参数,并且由这些参数计算武器在方向和高低上的响应公算偏差; b)第二,射击过程中方向和高低上的偏差呈正态分布。在matlab中取normrnd函数实现改功能&am…

《C语言深度解剖》二 static

最名不副实的关键字 static 认识多文件如下 extern 需要extern先声明在使用 生命没有开辟空间!100 在main.c里 所有的变量声明的时候,不能设置初始值 为什么要有头文件 头文件要包含 变量的声明int g_val 函数的声明void show(),没有函数的声明虽然可…