当前位置: 首页 > news >正文

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、源码&#xff08;比较短&#xff0c;贴一下&#xff09;1.1 重点&#xff1a;start0(); 三、研究Thread类的run()源码1、源码&#xff08;很关键&#xff0c;必须贴&#xff09; 四、创建线程的2种方式1…...

java基础之Java8新特性-方法引入

目录 1.简介 2.方法引入 方法引入遵循规范 方法引入种类 1.静态方法引入 2.对象方法引入 3.实例方法引入 4.构造函数引入 1.简介 方法引用是 Java 8 中引入的另一个重要特性&#xff0c;它提供了一种简洁的语法来直接引用现有方法或构造函数。方法引用可以看作是 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…...

编程基础 - 变量与常量

编程基础 - 变量与常量 返回序言及专栏目录 文章目录 编程基础 - 变量与常量前言一、变量是什么&#xff1f;二、为什么要有变量三、局部变量和全局变量四、常量五、只读变量小结 前言 变量是编程最重要知识点之一&#xff0c;从根本上讲&#xff0c;编程就是对数据的操作&a…...

Linux入门攻坚——12、Linux网络属性配置相关知识2

CentOS 7网络属性配置&#xff1a; 传统命名机制&#xff1a;以太网eth[0,1,2,...]&#xff0c;wlan[0,1,2...] 可预测功能的命名机制&#xff1a; udev支持多种不同的命名方案&#xff1a; Firmware &#xff0c;拓扑结构 在对待设备文件这块&#xff0c;Linux改…...

如何自己实现一个分布式事务

实现分布式事务是一个复杂的过程&#xff0c;它需要精心设计并考虑数据的一致性、系统的可用性和分区容错能力。分布式事务确保在分布式系统中&#xff0c;即使是跨多个数据库、服务或消息队列&#xff0c;事务要么完全成功&#xff0c;要么完全失败。 以下是实现分布式事务的…...

使用Nonebot编写QQ机器人

使用 NoneBot 这个工具&#xff0c;来编写 QQ 机器人。 安装基础软件 一、安装 NoneBot 库 直接使用 pip 安装即可 pip install nonebot二、安装酷Q 软件和 HTTP API 插件 酷Q 软件可以直接到官网下载&#xff0c;https://cqp.cc/b/news&#xff0c;或者可以到网盘下载&am…...

认识SpringBoot中的条件注解

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 循序渐进学SpringBoot ✨特色专栏&…...

使用PAI-DSW搭建基于LangChain的检索知识库问答机器人

教程简述 在本教程中&#xff0c;您将学习如何在阿里云交互式建模&#xff08;PAI-DSW&#xff09;中&#xff0c;基于LangChain的检索知识库实现知识问答。旨在建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。 LangChain是一个开源的框架&#xff0c…...

优雅的通过Shell脚本生成Go的程序包

前言 随着Go语言的普及&#xff0c;越来越多的开发人员选择使用Go编写代码。虽然越来越多的公司项目已使用持续集成/持续部署&#xff08;CI/CD&#xff09;工具&#xff0c;用于自动化构建、测试和部署Go程序包&#xff0c;但存在一些部署在ECS服务器的Go程序包或需要手动编译…...

益生菌抗癌?补充这种益生菌,抑制肝癌,还改善肠道健康

撰文 | 宋文法 肠道菌群&#xff0c;是人体不可分割的组成部分&#xff0c;生活在我们肠道内的数万亿细菌对健康起着重要作用&#xff0c;它们影响着人的新陈代谢、消化能力、抵御感染、控制人体对药物的反应&#xff0c;甚至还能预防某些癌症。 非酒精性脂肪肝病&#xff0c;是…...

LLM漫谈(二)| QAnything支持任意格式文件或数据库的本地知识库问答系统

一、QAnything介绍 QAnything (Question and Answer based on Anything) 是致力于支持任意格式文件或数据库的本地知识库问答系统&#xff0c;可断网安装使用。 您的任何格式的本地文件都可以往里扔&#xff0c;即可获得准确、快速、靠谱的问答体验。 目前已支持格式: PDF&…...

Linux环境vscode clang-format格式化:vscode clang format command is not available亲测有效!

问题现象 vscode安装了clang-format插件&#xff0c;但是使用就报错 问题原因 设置中配置的clang-format插件工具路径不正确。 解决方案-亲测有效&#xff01; 确认本地安装了clang-format工具&#xff1a;终端输入clang-format&#xff08;也可能是clang-format-13等版本…...

Vue3前端 响应式数据 知识点

一、ref(基本类型数据&#xff0c;也可以定义对象类型的响应式数据。此时底层用的还是reactive) ref 创建基本类型的响应式数据 作用:定义响应式变量语法: let xxx ref(初始值)返回值: 一个 RefImp1 的实例对象&#xff0c;简称 ref对象或ref&#xff0c;ref 对象的 value 属…...

golang数据库连接池设置多少比较合适,如何设置?

设置数据库连接池的大小需要综合考虑应用程序的需求、数据库系统的性能、服务器资源等因素。连接池大小的不合理设置可能导致性能问题或资源浪费。 以下是一些建议&#xff1a; 考虑应用程序的并发需求&#xff1a; 连接池的大小应该足够满足应用程序的并发需求。如果你的应用…...

一、Mybatis 简介

本章概要 简介持久层框架对比快速入门&#xff08;基于Mybatis3方式&#xff09; 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日上市!

在无数期待中&#xff0c;苹果全新产品Vision Pro头显终于定下上市日期。 彭博社记者马克古曼&#xff08;Mark Gurman&#xff09;于近日在X&#xff08;前推特&#xff09;平台爆料了这一信息&#xff0c;预计苹果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) {/…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...

加密通信 + 行为分析:运营商行业安全防御体系重构

在数字经济蓬勃发展的时代&#xff0c;运营商作为信息通信网络的核心枢纽&#xff0c;承载着海量用户数据与关键业务传输&#xff0c;其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级&#xff0c;传统安全防护体系逐渐暴露出局限性&a…...