多线程——认识线程(Thread)

目录

·前言

一、第一个多线程程序

1.程序编写

2.介绍jconsole

二、创建线程

1.继承Thread类

①重写run方法

②重写run方法,使用匿名内部类

2.实现Runnable接口

①重写run方法

②重写run方法,使用匿名内部类

③使用 lambda 表达式

三、多线程的优势

·结尾


·前言

        在前面文章我介绍了线程是什么,线程存在的意义还有线程与进程的区别,在本篇文章将会带大家在Java中进一步认识线程,会用Java语言写第一个多线程的程序,介绍在Java中如何创建线程,还要结束多线程编程的优势。

一、第一个多线程程序

1.程序编写

        在下面的程序中,我会让大家感受到多线程程序和普通程序的区别:

  1. 每个线程是独立的执行流;
  2. 多个线程之间是“并发”执行的。

         程序代码如下所示:

// 1. 创建自己的类,继承自 Thread
class MyThread extends Thread {// run 方法是该线程的入口方法@Overridepublic void run() {while (true) {// currentThread.getName()这个方法是获取当前线程的名字System.out.println("hello " + currentThread().getName());try {// sleep()这个方法会让当前线程进入休眠,()中参数是ms,为了减慢循环频率// 这个方法可能抛出异常,所以需要用 try-catch包住sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}public class ThreadDemo {public static void main(String[] args) {// 2. 根据上面创建的类,创建出实例Thread t1 = new MyThread();// 3. start(),这个方法用来启动线程,这才是创建出线程//    调用这个方法,才会真正调用系统 api ,在系统内核中创建出线程t1.start();// 在main里启动另一个死循环,直观感受两个线程在"并发"执行while (true) {System.out.println("hello " + Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

        程序运行结果如下图所示:

        由上图两个线程中的循环不断打印里面的内容,可以看出这两个线程是“并发”执行。

2.介绍jconsole

        jconsole是一个很方便的工具,可以利用这个工具来查看我们创建线程的相关信息,他的位置在我们的jdk的bin目录下,如下图所示:

        下面介绍一下jconsole的使用过程:

        关于使用jconsole需要补充介绍几点:

  1. jconsole 只能列出Java的进程,其他不是Java的程序无法分析;
  2. 打开 jconsole 可能不显示任何进程,可以使用管理员的方式来启动 jconsole(鼠标右键选择jconsole,选择“以管理员的身份运行”);
  3. 上面图中可以看见,我们创建的线程名叫 Thread-0 ,但是代码中,实例化的对象名叫t,其实答案就在刚才说的话里,我们创建的是一个对象,t是对象的名,不是我们所创建的线程名,我们创建的线程名默认叫 Thread-0、Thread-1……;
  4. 上图中,我们会发现,除了我们手动创建的线程,和main线程外,还有很多别的线程,这些线程都是JVM自带的线程,他们需要完成一些其他工作,比如垃圾回收,监控统计各种指标(如果代码出问题,可以通过这些指标给我们提供一些线索)等……;
  5. 线程是不断执行的,jconsole 是在我们选择线程的一瞬间,对线程来个“快照”,就把这一瞬间的状态展开显示出来。

        其实不光是 jconsole 可以看到线程的情况,在 idea 调试器中,也可以看道线程的情况,只不过我个人感觉 jconsole 比较方便,所以就不再介绍 idea 中的调试器了。

二、创建线程

        下面我来介绍几种Java中创建线程的方式:

1.继承Thread类

①重写run方法

// 继承 Thread 重写 run 方法
class MyThread extends Thread {@Overridepublic void run() {System.out.println("hello thread!!!");}
}public class ThreadDemo2 {public static void main(String[] args) {// 实例化一个线程对象Thread t = new MyThread();// 真正的去申请系统线程,参与 CPU 调度t.start();}
}

②重写run方法,使用匿名内部类

// 继承 Thread ,重写 run 方法,使用匿名内部类
public class ThreadDemo3 {public static void main(String[] args) {Thread t = new Thread(){// 指定线程任务@Overridepublic void run() {System.out.println("hello thread");}};// 真正的去申请系统线程,参与 CPU 调度t.start();}
}

2.实现Runnable接口

①重写run方法

// 创建一个 Runnable 的实现类,并实现 run 方法
// Runnable 主要描述的是线程的任务
class MyThread2 implements Runnable {@Overridepublic void run() {System.out.println("hello thread!!!");}
}public class ThreadDemo4 {public static void main(String[] args) {// 实例化 Runnable 对象Runnable runnable = new MyThread2();// 实例化线程对象,并绑定任务Thread t = new Thread(runnable);// 真正的去申请系统线程,参与 CPU 调度t.start();}
}

②重写run方法,使用匿名内部类

// 通过 Runnable 匿名内部类创建一个线程
public class ThreadDemo5 {public static void main(String[] args) {Thread t = new Thread(new Runnable() {// 指定线程任务@Overridepublic void run() {System.out.println("hello thread!!!");}});// 申请系统线程参与CPU调度t.start();}
}

③使用 lambda 表达式

        lambda表达式可以简化函数式接口的使用。什么是函数式接口呢?就是一个有且只有一个抽象方法的普通接口,Runnable接口就是一个函数式接口,所以可以使用 lambda 表达式来创建 Runnable 的子类对象,进而创建一个线程,代码如下所示:

// 通过 lambda 表达式的方式创建一个线程
public class ThreadDemo6 {public static void main(String[] args) {Thread t = new Thread(()->{// 指定任务: 打印 hello thread!!System.out.println("hello thread!!");});// 申请系统线程参与CPU调度t.start();}
}

        上述的五种创建线程的方式,我本人比较喜欢用 lambda 表达式的方式进行创建线程,因为这种方式比较简便。 

三、多线程的优势

        使用多线程的方式可以加快运行速度,可以举一个例子,如下图所示:

        在一个房间中,有100只烤鸡,此时需要房间中的滑稽老哥把这些鸡给吃完,可想而知,这样吃下去的速度会很慢,为了加快吃鸡效率,我们可以再邀请一个个滑稽老哥一起吃鸡,如下图所示: 

        这样,一个滑稽老哥吃50只烤鸡,效率明显就快了很多,以此类推,我们还可以再多邀请几个滑稽老哥,如下图所示:         现在,邀请了更多的滑稽老哥,吃鸡的速度变得更快了,但是,不是说引入的滑稽老哥越多效率就会越快,如下图所示:

        上图我们可以看出,邀请的滑稽老哥到达一定数量之后,再邀请更多的滑稽老哥,吃鸡的效率也没有办法继续提升了,这是因为桌子坐不下了。

        上面列举的例子中,滑稽老哥就是我们的线程,烤鸡就是我们要执行的任务,多线程的优势就是通过引入多个线程可以加快执行任务的效率,但是也不能引入太多的线程,就像上图所示那样,线程数量太多,各个线程之间就会互相竞争CPU的资源(CPU核心数有限),这样非但不会提高效率,反而还会增加调度的开销。 

·结尾

        文章到这就快结束了,本篇文章是在Java中利用多线程编程的一个初始篇章,这里介绍了创建线程的几种方式,编写的第一个多线程程序,介绍了多线的优势,在下一个篇文章中我会对java中Thread类再进行进一步的讲解,如果本篇文章对你有帮助的话,希望能三连支持一下咯,您的支持就是我最大的动力,我们下一篇文章再见吧,┏(^0^)┛~~~

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

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

相关文章

解决MySQL报Incorrect datetime value错误

目录 一、前言二、问题分析三、解决方法 一、前言 欢迎大家来到权权的博客~欢迎大家对我的博客进行指导,有什么不对的地方,我会及时改进哦~ 博客主页链接点这里–>:权权的博客主页链接 二、问题分析 这个错误通常出现在尝试将一个不…

OpenCV学堂 | YOLOv8官方团队宣布YOLOv11 发布了

本文来源公众号“OpenCV学堂”,仅用于学术分享,侵权删,干货满满。 原文链接:YOLOv8官方团队宣布YOLOv11 发布了 引言 YOLO11是Ultralytics YOLO系列实时目标检测器的最新迭代版本,它以尖端的准确性、速度和效率重新…

Mybatis-Plus新花样(一)

一. ActiveRecord Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。 在MyBatisPlus中,AR模式即在实体类中封装了对数据库的访问,而不…

Qt_绘图

目录 1、绘图核心类 2、QPainter类的使用 2.1 绘制线段 2.2 绘制矩形 2.3 绘制圆形 2.4 绘制文本 3、QPen类的使用 3.1 使用画笔 4、QBrush类的使用 4.1 使用画刷 5、绘制图片 5.1 测试QPixmap 5.1.1 图片移动 5.1.2 图标缩小 5.1.3 旋转图片 5.1.4 将…

比较10大热门低代码开发平台及其适用性

本文介绍10款主流低代码开发平台,包括ZohoCreator、OutSystems、Mendix等,它们各具特色,如定制能力强、集成方便、全栈开发等,适合不同企业快速构建应用程序,提升开发效率。 一、Zoho Creator Zoho Creator低代码开发…

回溯大总结

目录 0、基础什么是回溯?回溯法解决的问题回溯模板 1、组合问题77. 组合216.组合总和III17. 电话号码的字母组合39. 组合总和:40.组合总和II 0、基础 什么是回溯? 回溯是一种穷举的搜索算法,并不是一个高效的算法,当…

9.数据结构与算法-单链表,循环链表和双向链表的比较////顺序表和链表的比较

单链表,循环链表和双向链表的时间效率比较 顺序表和链表的区别 存储密度

坡印廷矢量(也叫功率流密度,对面积积分就是功率)

坡印廷矢量在静电场,静磁场,恒定电流的电场,和时变电磁场中的表达式不同。 我们看时变电磁场的坡印廷矢量 坡印廷矢量就等于这个,其中的电场和磁场是实数表示的 坡印廷矢量用复数形式的场求 这里的E和H是复数表示的场&#xff0…

Qt界面优化——QSS

文章目录 QSS基本语法使用示例样式和代码分离选择器用法子控件选择器伪类选择器盒子模型控件样式示例按钮复选框输入框列表框菜单 登录界面 QSS基本语法 Qt对界面进行优化,主要采用的是QSS。 选择器 {属性名: 属性值; }选择器:先选择某个/类控件&#…

2022年6月 Frontier 获得性能第一的论文翻译

为百万兆级加速架构做高性能 Linpack 优化 摘要 我们详细叙述了在 rocHPL 中做的性能优化,rocHPL 是 AMD 对 HPL 基准的开源实现,主要是针对节点进行优化的架构,是为百万兆级系统而设计的,比如:Frontier suppercomput…

K8S部署流程

一、war打包镜像(survey,analytics,trac系统) 代码打包成war准备tomcat的server.xml文件&#xff0c;修改connector中8080端口为项目的端口 修改前&#xff1a; <Connector port"8080" protocol"HTTP/1.1"connectionTimeout"20000"redirect…

你的虚拟猫娘女友,快来领取!--文心智能体平台

文章目录 一、引言二、赛事介绍2.1 简介2.2 比赛时间2.3 大赛具体链接2.4 第一期赛题 三、智能体创建流程3.1 进入文心智能体平台3.1 创建智能体3.1 虚拟猫娘女友特性3.1 智能体调优 四、引言智能体测试五、结语 一、引言 我是热爱生活的通信汪&#xff0c;今天这篇博文记录一…

【STM32单片机_(HAL库)】4-2-1【定时器TIM】定时器输出PWM实现呼吸灯实验

1.硬件 STM32单片机最小系统LED灯模块 2.软件 pwm驱动文件添加定时器HAL驱动层文件添加GPIO常用函数定时器输出PWM配置步骤main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "pwm.h"int main(void) {HA…

疾风大模型气象,基于气象数据打造可视化平台

引言 随着气象数据的广泛应用&#xff0c;越来越多的行业依赖天气预报与气候分析来做出决策。从农业、航空、能源到物流&#xff0c;气象信息无时不刻影响着各行各业的运作。然而&#xff0c;气象数据本身复杂且多样&#xff0c;如何将这些数据转化为直观、易于理解的图形和信…

TypeScript 算法手册【插入排序】

文章目录 TypeScript 算法手册 - 插入排序1. 插入排序简介1.1 插入排序定义1.2 插入排序特点 2. 插入排序步骤过程拆解2.1 选择当前元素2.2 寻找插入位置2.3 插入元素 3. 插入排序的优化3.1 二分查找插入排序案例代码和动态图 4. 插入排序的优点5. 插入排序的缺点总结 【 已更新…

每日OJ题_牛客_JZ61扑克牌顺子_排序_C++_Java

目录 牛客_JZ61扑克牌顺子_排序 题目解析 C代码 Java代码 牛客_JZ61扑克牌顺子_排序 扑克牌顺子_牛客题霸_牛客网 描述&#xff1a; 现在有2副扑克牌&#xff0c;从扑克牌中随机五张扑克牌&#xff0c;我们需要来判断一下是不是顺子。 有如下规则&#xff1a; 1. A为1&a…

带徒实训项目实战讲义分享:ApiFirst文档对比功能页面开发2

前一篇&#xff1a;带徒实训项目实战讲义分享&#xff1a;ApiFirst文档对比功能页面开发 亲爱的学员朋友们好&#xff0c;本小节跟小卷一起来学习用thymeleaf模板技术来渲染数据模型到表格中&#xff0c;通过本小节的学习&#xff0c;你会真正将thymeleaf模板技术应用到实处&a…

红黑树操作图文详解,包学会

RB-tree(红黑树) 1、概要 红黑树是一种自平衡的二叉搜索树&#xff0c;它在插入、删除和查找通过一定的规则可以把时间复杂度控制在O(log n)内。红黑树广泛应用域各种场景&#xff0c;如C的map和set底层实现等。 红黑树不仅是个二叉搜索树&#xff0c;而且必须满足以下性质&…

【Xcode Command Line Tools】安装指南

安装指令 xcode-select --install安装 完成安装 验证 $ xcode-select -p /Library/Developer/CommandLineTools

沂机管理系统存在存储型XSS漏洞

漏洞描述 沂机管理系统存在存储型XSS漏洞&#xff0c;窃取用户Cookie获取用户信息 漏洞复现 body"后台管理系统演示版" POC GET /data/Ajax.aspx?methoduser_save&frandom0.15233733802978144&FCloud_OrgID1&FCloud_UserID167636&FCloud_EmpID1…