【JavaEE多线程】线程的创建

系列文章目录

🌈座右铭🌈:人的一生这么长、你凭什么用短短的几年去衡量自己的一生!

💕个人主页:清灵白羽 漾情天殇_计算机底层原理,深度解析C++,自顶向下看Java-CSDN博客

❤️相关文章❤️:清灵白羽 漾情天殇-CSDN博客


目录

系列文章目录

前言

一、继承Thread类

        1、创建自定义线程类

        2、创建线程对象并且启动

        3、线程生命周期

        拓展:start()和run()的区别

        1、run()方法

        2、start()方法

二、实现Runnable接口

        1、实现Runnable接口

        1、创建线程任务类

        2、创建线程对象并且传入线程任务

        3、启动线程

        2、以上两种方式的区别

        1、Runnable当中的this引用

        2、Thread继承类当中的this引用

三、匿名内部类创建线程

        1、匿名内部类创建Thread对象

        2、匿名内部类创建Runnable子类对象


前言

        今天的这篇文章主要为大家介绍一下Java当中的线程是如何创建的,这里为大家分别介绍了几种方式,内容比较简单,但是涉及到了之前JavaSE的一些语法细节,如果有遗忘的话大家可以翻阅我之前的文章,能够帮助到各位就是对我最大的鼓励!


一、继承Thread类

        首先我提示一下这里使用到了多态的语法概念如果对于这方面内容有不了解的话可以先去复习一下多态的概念,或者看我之前介绍过有关多态的文章。

        1、创建自定义线程类

        首先我们需要创建一个自定义的线程类,该类继承自Thread类,并且重写了其中的run()方法,以定义线程的执行逻辑。

package Yangon;class MyThread extends Thread{@Overridepublic void run() {System.out.println("线程执行!");}
}
public class Main {
}

        2、创建线程对象并且启动

        创建自定义的线程类的对象,并且调用其start()方法,以启动线程。

public class Main {public static void main(String[] args) {Thread thread = new MyThread();thread.start();}
}

        这里就使用到了向上转型,使用多态。

        3、线程生命周期

        当调用线程对象的start()方法时,线程进入就绪状态,等待CPU的调度执行,一旦CPU调度到该线程的时候就会执行其中的run()方法,当run()方法执行完毕或者线程被中断的时候线程就会结束等待下一次调用或者直接销毁。

        我在这里多说一句,线程的创建并不一定要使用多态,也可以直接使用Thread来创建新的线程,直接给Thread传递一个Runnable(这个东西我一会会讲)即可。

public class Main {public static void main(String[] args) {Runnable myRunnable = () -> {// 在这里定义线程的执行逻辑System.out.println("MyThread is running...");};Thread myThread = new Thread(myRunnable);myThread.start();}
}

        拓展:start()和run()的区别

        在Java当中,线程的启动涉及到两个重要的方法,run方法和start方法,他们之间却有着很大的区别:

        1、run()方法

        只是Thread的一个普通的方法用以定义线程的执行逻辑,当我们直接调用一个线程对象的run方法的时候并不会线程新的线程,而是在当前线程当中执行run方法的代码。如果我们通过继承Thread类并且重写其run方法来创建新的线程时,当我们调用该线程的run方法实际上只是在当前线程中执行了自己定义的新线程的run方法,并没有新的线程产生,程序还是只有一个执行流。

        2、start()方法

        start()方法是一个用于启动一个新线程的重要方法,当我们调用一个线程对象的start方法的时候,系统会为该线程创建一个新的线程,并且在新线程当中调用run方法,同样的使用继承Thread类来创建新线程的方法时,我们调用start方法,系统产生一个新线程并且在新线程当中执行run方法,这个时候系统有两个执行流。这就是他们之间的区别。


二、实现Runnable接口

        1、实现Runnable接口

        1、创建线程任务类

        首先,我们需要创建一个类,实现Runnable接口,并且重写其中的run()方法,定义线程当中的执行逻辑。

class MyTask implements Runnable{@Overridepublic void run() {System.out.println("线程执行");}
}

        2、创建线程对象并且传入线程任务

        接下来我们需要创建一个Thread类的对象,并且将实现了Runnable接口的线程任务对象作为参数传递给Thread的构造方法。

public class Main {public static void main(String[] args) {Thread thread = new Thread(new MyTask());thread.start();}
}

        3、启动线程

        最后我们只需要调用start()方法启动线程即可。通过实现Runnable接口来创建新线程的优势在于能够更好地支持面向对象的设计原则,并且提供了更好的线程任务与线程类的解耦,此外通过实现Runnable接口,多个线程可以共享同一个线程任务对象,避免了多重继承带来的局限性,因此我们推荐使用Runnable接口的方法创建新线程。

        2、以上两种方式的区别

        继承Thread类,直接使用this引用表示当前线程对象的引用,如果是实现Runnable接口,this表示的是MyTask的引用,需要使用Thread.currentThread()解释一下。

        1、Runnable当中的this引用

        在Java当中通过实现Runnable接口创建线程的时候,this引用关键字代表实现了Runnable接口的类的实例的引用(这句话有点拗口),而不是线程对象本身,因此我们在实现了Runnable接口的类当中使用this它将引用到该类的实例,而不是代表正在执行的线程对象。

        但是在某种情况下我们可能需要获取当前正在执行的线程对象的引用,例如在多线程环境下,你想要获取当前线程的一些属性或者执行某些操作,这个时候就需要使用Thread类的静态方法currentThread()来获取当前线程的引用。

class MyRunnable implements Runnable{@Overridepublic void run() {Thread thread = Thread.currentThread();System.out.println("当前线程的名称:" + Thread.currentThread().getName());System.out.println("当前线程的优先级:" + thread.getPriority());//Thread.currentThread().getName() 两种方式等价}
}
public class Main {public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);thread.start();}
}

        在上面的例子中,通过调用Thread.currentThread()方法,我们获取了当前正在执行的线程对象的引用,并通过该引用调用了Thread类的一些方法,如getName()和getPriority()来获取线程的名称和优先级。这样就能够在Runnable接口实现类中获取到当前线程对象的引用,并对其进行操作。

        2、Thread继承类当中的this引用

        当我们继承Thread类来创建线程的时候,在线程的运行过程当中,this关键字确实代表线程对象的引用,也就是说this指向了正在执行该线程的Thread对象。

class MyThread extends Thread{@Overridepublic void run() {System.out.println("当前线程名称:" + this.getName());System.out.println("当前线程优先级:" + this.getPriority());System.out.println("MyThread is running");}
}
public class Main {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();}
}

        在这个例子中,当你调用myThread.start()时,系统会创建一个新的线程,并调用MyThread类的run()方法。在run()方法中,this关键字代表了当前线程对象,我们可以通过this来访问当前线程的属性和方法,比如getName()和getPriority()来获取当前线程的名称和优先级。


三、匿名内部类创建线程

        1、匿名内部类创建Thread对象

public class Main {public static void main(String[] args) {Thread thread = new Thread(){@Overridepublic void run() {System.out.println("MyThread is running");}};thread.start();}
}

        在这个例子当中,我们创建了一个Thread的匿名子类,并且重写了其run()方法,然后直接在main方法当中创建了这个Thread子类的对象,然后调用其start()方法启动线程,这种方式可以省略编写一个具体的Thread子类的步骤,使得代码更加简洁。

        2、匿名内部类创建Runnable子类对象

public class Main {public static void main(String[] args) {Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("Runnable is running");}};Thread thread = new Thread(runnable);thread.start();}
}

        在这个例子中,我们创建了一个实现了Runnable接口的匿名内部类,并重写了其run()方法。然后,我们将这个匿名内部类的对象传递给了Thread类的构造方法,从而创建了一个新的线程对象。最后调用start()方法启动了线程。

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

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

相关文章

【代码】Python3|Requests 库怎么继承 Selenium 的 Headers (2024,Chrome)

本文使用的版本: Chrome 124Python 12Selenium 4.19.0 版本过旧可能会出现问题,但只要别差异太大,就可以看本文,因为本文对新老版本都有讲解。 文章目录 1 难点解析和具体思路2 注意事项2.1 PDF 资源获取时注意事项2.2 Capabiliti…

asp.net core 依赖注入后的服务生命周期

ASP.NET Core 依赖注入(DI)容器支持三种服务的生命周期选项,它们定义了服务实例的创建和销毁的时机。理解这三种生命周期对于设计健壯且高效的应用程序非常重要: 瞬时(Transient): 瞬时服务每次…

西瓜书学习——第一、二章笔记

[] 什么是机器学习? 研究关于“学习算法”(一类能从数据中学习出其背后潜在规律的算法)的一门学科。 PS:深度学习指的是神经网络那一类学习算法,因此是机器学习的子集。 假设空间和版本空间 举个栗子:假设现已收集到某地区近几年的房价和学校数量数据&#xf…

CloudCompare 整体架构

CloudCompare 是一个开源的大规模点云处理软件,内置了点云渲染和各种点云算法,还有插件化拓展,非常适合作为点云相关软件的基础程序进行二次开发。源码地址:https://github.com/CloudCompare/CloudCompare 这里记录一下项目的主要模块目录和他们做的事情。 编译和依赖 编…

ChatGPT及GIS、生物、地球、农业、气象、生态、环境科学领域案例

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮,可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

SRIO系列-时钟逻辑与复位逻辑

一、前言 上一篇讲述了SRIO协议的基本概念,传输的HELLO帧格式、事务类型等,本篇说一下SRIO IP核的时钟关系。 基本的IP设置可以参考此篇文章:【高速接口-RapidIO】Xilinx SRIO IP 核详解-CSDN博客 二、时钟关系 PHY可以在两个时钟域上运行…

【Java EE】多线程-进阶-锁策略

目录 1.常见的锁策略 1.1乐观锁 vs 悲观锁 1.2重量级锁 vs 轻量级锁 1.3自旋锁(Spin Lock) 1.4公平锁 vs 非公平锁 1.5可重入锁和不可重入锁 1.6读写锁 2.CAS 2.1什么事CAS 2.2CAS是怎么实现的 2.3CAS有哪些应用 2.3.1实现原子类 2.3.2实现自…

自动驾驶(八十四)---------中间件对比分析

很久没有写博客了,CSDN无故非法删了我第82篇,让我很恼火,一直提不起兴趣重新写一遍第82篇。但回初心,知识需要用自己的语言输出,所以今天对比分析自动驾驶中间件: 1. 中间件介绍 在自动驾驶架构中&#xf…

SAP打印输出设置

SAP打印输入有很多方式,适合不同的应用场景。 一.打印输出总体概览图 二.前台打印 这个是比较常见的,前端打印的出现减轻了管理员的工作量,用户可以选择自己电脑上的打印机输出,不需要所有打印机都在SAP平台中进行配置&#xff0…

【Next】动态路由、加载 UI 和流式传输

动态路由 动态段作为 params 属性传递给 layout、page、route 和 generateMetadata 函数。 /app/blog/[slug]/page.tsx export default function Page({params}: {params:{slug:string}}) {return <h1>Slug Page -- {params.slug}</h1> };/app/shop/[...slug]/pa…

(vue)el-select选择框加全选/清空/反选

(vue)el-select选择框加全选/清空/反选 <el-form-item label"批次"><el-selectv-model"formInline.processBatch"multiplecollapse-tagsfilterableplaceholder"请选择"style"width: 250px"no-data-text"请先选择企业、日…

常用的启发式算法有哪些

常用的启发式算法主要包括模拟退火算法&#xff08;SA&#xff09;、蚁群算法&#xff08;ACO&#xff09;、粒子群算法&#xff08;PSO&#xff09;、遗传算法&#xff08;GA&#xff09;、禁忌搜索算法&#xff08;TS&#xff09;以及超启发式算法&#xff08;Hyper-Heuristi…

Java使用documents4j将word和excel转pdf

pom.xml添加documents4j依赖 <!-- documents4j --> <dependency><groupId>com.documents4j</groupId><artifactId>documents4j-local</artifactId><version>1.0.3</version> </dependency> <!-- documents4j 转 wor…

《Kubernetes部署篇:基于Kylin V10+ARM架构CPU+外部etcd使用containerd部署K8S 1.26.15容器版集群(一主多从)》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;企业级K8s集群运维实战 1、在当前实验环境中安装K8S1.25.14版本&#xff0c;出现了一个问题&#xff0c;就是在pod中访问百度网站&#xff0c;大…

Java基础知识总结(59)

&#xff08;1&#xff09;Set集合 Set也是集合中的一个容器&#xff0c;程序可以依次把若干个对象放进Set&#xff0c;但是Set无法保存元素添加的顺序&#xff0c; Set不允许包含相同的元素&#xff0c;如果把两个相同的元素加入同一个Set中&#xff0c;则添加失败&#xff0…

Openlayers动态刷新Arcgis MapServer服务图层

Openlayers动态刷新Arcgis MapServer服务图层 最近做一个图层编辑的功能&#xff0c;在前端新增一个图块之后需要刷新Arcgis切片服务&#xff0c;实时显示效果。刚开始使用source的refresh方法&#xff0c;结果不生效&#xff0c;后来在source上更新一个时间戳参数实现了刷新切…

UTS iOS插件

1、UTS插件无法出现 再uniapp x中使用时&#xff0c;必须给这个插件高度和宽度&#xff0c;否则出不来&#xff01; <uts-hello-view buttonText"点击按钮内容" style"width:375px;height: 375px;background-color: aqua;"></uts-hello-view>…

python后端相关知识点汇总(十二)

python知识点汇总十二 1、什么是 C/S 和 B/S 架构2、count(1)、count(*)、count(列名)有啥区别&#xff1f;3、如何使用线程池3.1、为什么使用线程池&#xff1f; 4、MySQL 数据库备份命令5、supervisor和Gunicorn6、python项目部署6.1、entrypoint.sh制作6.2、Dockerfile制作6…

vue 的报告页面,生成pdf,使用html2canvas , 下载pdf格式文件。多页分页下载

1. 新建一个js 文件 &#xff0c; 命名 为 html2canvas.js ,html2canvas 文件和jspdf.min.js 放同一目录下。下载文件已上传啦 2. 在vue 文件中引入html2canvas.js 文件 <script>import * as html2Canvas from ./html2canvas.js </script> 3 点击下载&#xff…

oracle insert操作分批量提交

对临时表做insert插入时没有做批量提交&#xff0c;可能会导致undo表空间撑爆&#xff0c;修改脚本对插数进行2万一次的批量提交&#xff0c;并且修改索引和同义词创建时间在插数操作结束后。 原语句&#xff1a; insert into 目标表 select * from 源表;改为2w次一提交&…