Java多线程-Thread类的run方法
Java多线程-Thread类的run方法
- 一、背景
- 二、研究Thread类的start()源码
- 1、源码(比较短,贴一下)
- 1.1 重点:start0();
- 三、研究Thread类的run()源码
- 1、源码(很关键,必须贴)
- 四、创建线程的2种方式
- 1、继承Thread,并覆写run方法
- 2、传入一个实现了run方法的Runnable接口的实现类
- 五、到底执行哪个run方法?
一、背景
- 在Java中,要使用多线程,很显然先要创建线程。
- Java将线程抽象为Thread类。创建线程的第一步:
new Thread() - 创建好Thread对象后,接下来,就是要启动线程,并执行线程需要做的事情:Thread对象.start();
(1)首先会启动线程;
(2)然后调用run方法();
二、研究Thread类的start()源码
1、源码(比较短,贴一下)
public synchronized void start() {if (threadStatus != 0)throw new IllegalThreadStateException();group.add(this);boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {}}
}
1.1 重点:start0();
- 源码
private native void start0();
- 是一个本地方法。也很好理解,Java的线程是交由操作系统来管理的。
start0()方法是Java中的一个
本地方法,也就是说它是用其他语言(通常是C或C++)实现的。
其主要逻辑是创建一个新的系统级线程,并在新线程上执行run()方法。
Java中的线程是基于操作系统的原生线程实现的,而start0()方法主要就是与操作系统进行交互,创建和启动新的系统级线程。
具体来说,start0()方法的执行逻辑一般包括以下步骤:
(1)申请系统资源创建一个新的系统级线程。
(2)将Java线程对象与新创建的系统级线程进行关联。
(3)设置线程的优先级和栈大小等线程属性。
(3)在新的系统级线程上调用Java线程对象的run()方法。
(4)如果run()方法执行结束或发生异常,清理系统级线程资源。
以上执行逻辑可能因不同的JVM实现和不同的操作系统有所不同,具体实现代码可以在JVM的源代码中找到。
三、研究Thread类的run()源码
1、源码(很关键,必须贴)
@Override
public void run() {if (target != null) {target.run();}
}
- Thread类:
public class Thread implements Runnable
Runnable的源码:
@FunctionalInterface
public interface Runnable {public abstract void run();
}
既然Thread类实现了Runnable接口,就要覆写run方法。
- target是什么?
public class Thread implements Runnable {......private Runnable target;......
}
- 用户可以通过这个构造方法传入target:
public Thread(Runnable target) {init(null, target, "Thread-" + nextThreadNum(), 0);
}
四、创建线程的2种方式
通过上面的分析,要让线程执行某段逻辑的关键是,实现run方法。
有2种方式:
(1)继承Thread,并覆写run方法
(2)传入一个实现了run方法的Runnable接口的实现类
1、继承Thread,并覆写run方法
- 示例
public class PrintEvenThread extends Thread {@Overridepublic void run() {// 遍历100以内的偶数for (int i = 0; i < 100; i++) {if (i % 2 == 0) {System.out.println(Thread.currentThread().getName() + ":" + i);}}}
}public class PrintOddThread extends Thread {@Overridepublic void run() {// 遍历100以内的奇数for (int i = 0; i < 100; i++) {if (i % 2 != 0) {System.out.println(Thread.currentThread().getName() + ":" + i);}}}
}
public class PrintThreadTest {@Testpublic void testTwoPrintThread() {PrintEvenThread printEvenThread = new PrintEvenThread();PrintOddThread printOddThread = new PrintOddThread();printEvenThread.start();printOddThread.start();}
}
- 还可以:匿名类的匿名对象的方式
new Thread() {@Overridepublic void run() {for (int i = 0; i < 100; i++) {if (i % 2 != 0) {System.out.println(Thread.currentThread().getName() + ":" + i);}}}
}.start();
2、传入一个实现了run方法的Runnable接口的实现类
- 示例 (匿名类的匿名对象)
public class LearnCreateThreadMain3 {public static void main(String[] args) {new Thread(new PrintEven()).start();}
}class PrintEven implements Runnable {@Overridepublic void run() {for (int i = 0; i < 10; i++) {if (i % 2 == 0) {System.out.println(i);}}}
}
- 还可以:匿名类的匿名对象的方式
new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 100; i++) {if (i % 2 != 0) {System.out.println(Thread.currentThread().getName() + ":" + i);}}}}).start();
五、到底执行哪个run方法?
- 示例
public class LearnCreateThreadMain4 {public static void main(String[] args) {Hi hi = new Hi();new Thread(hi) {@Overridepublic void run() {System.out.println("hello~");}}.start();}
}class Hi implements Runnable {@Overridepublic void run() {System.out.println("Hi~");}
}
- 看懂了“三、研究Thread类的run()源码”,很容易回答:执行的是Thread子类对象的run方法。也就是输出:
hello~。 - 如果子类没有覆写Thread的run()方法,那么执行的代码是:
@Override
public void run() {if (target != null) {target.run();}
}
- 一旦子类覆写了,那执行的就是子类的run()方法了。
相关文章:
Java多线程-Thread类的run方法
Java多线程-Thread类的run方法 一、背景二、研究Thread类的start()源码1、源码(比较短,贴一下)1.1 重点:start0(); 三、研究Thread类的run()源码1、源码(很关键,必须贴) 四、创建线程的2种方式1…...
java基础之Java8新特性-方法引入
目录 1.简介 2.方法引入 方法引入遵循规范 方法引入种类 1.静态方法引入 2.对象方法引入 3.实例方法引入 4.构造函数引入 1.简介 方法引用是 Java 8 中引入的另一个重要特性,它提供了一种简洁的语法来直接引用现有方法或构造函数。方法引用可以看作是 Lambd…...
K8S中的hostPort、NodePort 、targetPort、port、containerPort 的区别
Dockerfile的EXPOSE Dockerfile中端口的声明: EXPOSE <端口1> [<端口2>...] 所以:EXPOSE的 第一个作用:只是说明docker容器开放了哪些端口,并没有将这些端口实际开放了出来!更多的作用是告诉运维人员或容器操作人员我开放了容器的哪些端口,只是一种说明。 …...
SpringBoot整合FreeMarker模板引擎
中文官方参考手册 http://freemarker.foofun.cn/ 1.先加入FreeMarker依赖 <dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version> </dependency>2.新建一个FreeMark…...
编程基础 - 变量与常量
编程基础 - 变量与常量 返回序言及专栏目录 文章目录 编程基础 - 变量与常量前言一、变量是什么?二、为什么要有变量三、局部变量和全局变量四、常量五、只读变量小结 前言 变量是编程最重要知识点之一,从根本上讲,编程就是对数据的操作&a…...
Linux入门攻坚——12、Linux网络属性配置相关知识2
CentOS 7网络属性配置: 传统命名机制:以太网eth[0,1,2,...],wlan[0,1,2...] 可预测功能的命名机制: udev支持多种不同的命名方案: Firmware ,拓扑结构 在对待设备文件这块,Linux改…...
如何自己实现一个分布式事务
实现分布式事务是一个复杂的过程,它需要精心设计并考虑数据的一致性、系统的可用性和分区容错能力。分布式事务确保在分布式系统中,即使是跨多个数据库、服务或消息队列,事务要么完全成功,要么完全失败。 以下是实现分布式事务的…...
使用Nonebot编写QQ机器人
使用 NoneBot 这个工具,来编写 QQ 机器人。 安装基础软件 一、安装 NoneBot 库 直接使用 pip 安装即可 pip install nonebot二、安装酷Q 软件和 HTTP API 插件 酷Q 软件可以直接到官网下载,https://cqp.cc/b/news,或者可以到网盘下载&am…...
认识SpringBoot中的条件注解
✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏&…...
使用PAI-DSW搭建基于LangChain的检索知识库问答机器人
教程简述 在本教程中,您将学习如何在阿里云交互式建模(PAI-DSW)中,基于LangChain的检索知识库实现知识问答。旨在建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。 LangChain是一个开源的框架,…...
优雅的通过Shell脚本生成Go的程序包
前言 随着Go语言的普及,越来越多的开发人员选择使用Go编写代码。虽然越来越多的公司项目已使用持续集成/持续部署(CI/CD)工具,用于自动化构建、测试和部署Go程序包,但存在一些部署在ECS服务器的Go程序包或需要手动编译…...
益生菌抗癌?补充这种益生菌,抑制肝癌,还改善肠道健康
撰文 | 宋文法 肠道菌群,是人体不可分割的组成部分,生活在我们肠道内的数万亿细菌对健康起着重要作用,它们影响着人的新陈代谢、消化能力、抵御感染、控制人体对药物的反应,甚至还能预防某些癌症。 非酒精性脂肪肝病,是…...
LLM漫谈(二)| QAnything支持任意格式文件或数据库的本地知识库问答系统
一、QAnything介绍 QAnything (Question and Answer based on Anything) 是致力于支持任意格式文件或数据库的本地知识库问答系统,可断网安装使用。 您的任何格式的本地文件都可以往里扔,即可获得准确、快速、靠谱的问答体验。 目前已支持格式: PDF&…...
Linux环境vscode clang-format格式化:vscode clang format command is not available亲测有效!
问题现象 vscode安装了clang-format插件,但是使用就报错 问题原因 设置中配置的clang-format插件工具路径不正确。 解决方案-亲测有效! 确认本地安装了clang-format工具:终端输入clang-format(也可能是clang-format-13等版本…...
Vue3前端 响应式数据 知识点
一、ref(基本类型数据,也可以定义对象类型的响应式数据。此时底层用的还是reactive) ref 创建基本类型的响应式数据 作用:定义响应式变量语法: let xxx ref(初始值)返回值: 一个 RefImp1 的实例对象,简称 ref对象或ref,ref 对象的 value 属…...
golang数据库连接池设置多少比较合适,如何设置?
设置数据库连接池的大小需要综合考虑应用程序的需求、数据库系统的性能、服务器资源等因素。连接池大小的不合理设置可能导致性能问题或资源浪费。 以下是一些建议: 考虑应用程序的并发需求: 连接池的大小应该足够满足应用程序的并发需求。如果你的应用…...
一、Mybatis 简介
本章概要 简介持久层框架对比快速入门(基于Mybatis3方式) 1.1 简介 https://mybatis.org/mybatis-3/zh/index.html MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投G…...
苹果Vision Pro将于1月27日上市!
在无数期待中,苹果全新产品Vision Pro头显终于定下上市日期。 彭博社记者马克古曼(Mark Gurman)于近日在X(前推特)平台爆料了这一信息,预计苹果Vision Pro头显将于2024年1月27日率先在美国上市。 在过去看…...
密码学(一)
文章目录 前言一、Cryptographic Primitives二、Cryptographic Keys2.1 Symmetric key cryptography2.2 asymmetric key cryptography 三、Confidentiality3.1 Symmetric key encryption algorithms3.2 asymmetric key block ciphers3.3 其他 四、Integrity4.1 secure hashing …...
VueRouter
1、用户权限问题 可以在路由全局前置守卫判断当前vuex里是否有token 有token值证明刚才登录过, 无token值证明未登录 router.beforeEach((to, from, next) > {const token store.state.tokenif (token) {// 如果有token, 证明已登录if (!store.state.userInfo.username) {/…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
Git 命令全流程总结
以下是从初始化到版本控制、查看记录、撤回操作的 Git 命令全流程总结,按操作场景分类整理: 一、初始化与基础操作 操作命令初始化仓库git init添加所有文件到暂存区git add .提交到本地仓库git commit -m "提交描述"首次提交需配置身份git c…...
理想汽车5月交付40856辆,同比增长16.7%
6月1日,理想汽车官方宣布,5月交付新车40856辆,同比增长16.7%。截至2025年5月31日,理想汽车历史累计交付量为1301531辆。 官方表示,理想L系列智能焕新版在5月正式发布,全系产品力有显著的提升,每…...
标注工具核心架构分析——主窗口的图像显示
🏗️ 标注工具核心架构分析 📋 系统概述 主要有两个核心类,采用经典的 Scene-View 架构模式: 🎯 核心类结构 1. AnnotationScene (QGraphicsScene子类) 主要负责标注场景的管理和交互 🔧 关键函数&…...
