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

【JaveEE】线程的创建及常见方法解析(Tread类)

目录

1.Tread类介绍

2线程的构造方法——创建线程

1.继承Thread类,重写run()方法

2.使用Runnbable接口创建线程

3.继承 Thread, 重写 run, 使用匿名内部类

4.实现 Runnable, 重写 run, 使用匿名内部类

5.使用 lambda 表达式(重点掌握)

3.Tread类常见方法解读 

3.1Tread类常见构造方法 

3.2 Tread类的几个常见属性

3.3启动一个线程-start()方法

3.4中断一个线程

3.5等待一个线程-join() 

3.6休眠线程

3.7 实现一个简单的多线程

4.线程的状态

4.1线程的六种状态 

4.2线程状态和状态转移


1.Tread类介绍

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联,每个执行流(线程),也需要有一个对象来描述, Thread 类的对象就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度、线程管理。

2线程的构造方法——创建线程

无论使用哪一个方法创建线程,我们都需要将其中的run方法重写(run方法中写入的是线程需要执行的任务),它的作用就相当于主线程的main方法。

1.继承Thread类,重写run()方法

这个构造方法没有参数,通过创造一个类继承Thread类来实现线程 ,线程必须重写run()方法才算完成。当我们new一个线程时,此时的线程还没开始执行,再用创建的类调用start()方法才算运行了这个线程。

class TestTread extends Thread{@Overridepublic void run() {System.out.println("this tread1");}
}
public class testDemo2 {public static void main(String[] args) {Thread thread=new TestTread();thread.start();}}

2.使用Runnbable接口创建线程

我们可以看出,该构造方法的参数类型是一个接口类,因此我们需要创建一个类来实现这个接口,再new一个实现Runnable的类对象,再new一个线程,将之前创建的对象放入到参数这里。

class TestTread2 implements Runnable {@Overridepublic void run() {System.out.println("this t2");}
}
public class testDemo2 {public static void main(String[] args) {//new一个实现Runnable接口的对象TestTread2 testTread2=new TestTread2();//传入参数完成线程的创建Thread t2=new Thread(testTread2);t2.start();}}

3.继承 Thread, 重写 run, 使用匿名内部类

 使用匿名内部类可以省略创建对象的过程,可以减少资源消耗。

public class testDemo3 {public static void main(String[] args) {//通过Thread匿名内部类的方法创建一个线程Thread t1=new Thread() {@Overridepublic void run() {System.out.println("this t1");}};t1.start();}}

4.实现 Runnable, 重写 run, 使用匿名内部类

这个和3一样,可以少创建一个对象,减少资源的消耗。 

public class testDemo4 {public static void main(String[] args) {Thread t1=new Thread(new  Runnable() {@Overridepublic void run() {System.out.println("this t1");}});t1.start();}
}

5.使用 lambda 表达式(重点掌握)

它的实现原理和匿名内部类相似,这点不了解lambda表达式的,可以去看一下如何使用。

public class testDemo4 {public static void main(String[] args) Thread t2=new Thread(()->{System.out.println("this t2");});t2.start();}
}

3.Tread类常见方法解读 

3.1Tread类常见构造方法 

方法说明
Thread()创建线程对象
Thread(Runnable target)使用 Runnable 对象创建线程对象
Thread(String name)创建线程对象,并命名
Thread(Runnable target, String name)使用 Runnable 对象创建线程对象,并命名
【了解】Thread(ThreadGroup group,
Runnable target)
线程可以被用来分组管理,分好的组即为线程组,这
个目前我们了解即可

3.2 Tread类的几个常见属性

属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台线程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()
  • ID 是线程的唯一标识,不同线程不会重复。
  • 名称是各种调试工具用到。
  • 状态表示线程当前所处的一个情况,下面我们会进一步说明。
  • 优先级高的线程理论上来说更容易被调度到。
  • 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行
  • 是否存活,即简单的理解,为 run 方法是否运行结束了。
  • 线程的中断问题,下方会有解析

3.3启动一个线程-start()方法

调用 start 方法, 才算是在操作系统的底层创建出一个线程. 

public class testDemo4 {public static void main(String[] args) {Thread t1=new Thread(new  Runnable() {@Overridepublic void run() {System.out.println("this t1");}});t1.start();}
}

3.4中断一个线程

方法说明
public void interrupt()中断对象关联的线程,如果线程正在阻塞,则以异常方式通知,
否则设置标志位
public static boolean
interrupted()
判断当前线程的中断标志位是否设置,调用后清除标志位
public boolean
isInterrupted()
判断对象关联的线程的标志位是否设置,调用后不清除标志位
  • 使用 thread 对象的 interrupted() 方法通知线程结束 
public class testDemo6 {public static void main(String[] args) throws InterruptedException {Thread t1=new Thread(() ->{while (!Thread.interrupted()) {System.out.println(Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();break;}}});t1.start();Thread.sleep(1000*2);t1.interrupt();}
}

t1收到通知的方式有两种:

1.如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通知,清除中断标志.

  • 当出现 InterruptedException 的时候, 要不要结束线程取决于 catch 中代码的写法. 可以选择忽略这个异常, 也可以跳出循环结束线程(加break).

 2.否则,只是内部的一个中断标志被设置,thread 可以通过

  • Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志
  • Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志
  • 使用 Thread.isInterrupted() , 线程中断会清除标志位

标志位是否清除, 就类似于一个开关.
Thread.Interrupted() 相当于按下开关, 开关自动弹起来了. 这个称为 "清除标志位".

public class ThreadDemo {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()->{for (int i = 0; i < 10; i++) {// //打印标准位System.out.println(Thread.interrupted());}});thread.start();thread.interrupt();}
}

结果:

观察结果可以看出,已知interrupted()初始是true,之后就打印的值就是false,因为标志位已经被删除了。

  • 使用 Thread.currentThread().isInterrupted() , 线程中断标记位不会清除

 标志位是否清除, 就类似于一个开关.
Thread.currentThread().isInterrupted() 相当于按下开关之后, 开关弹不起来, 这个称为"不清除标志位".

public class ThreadDemo {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()->{for (int i = 0; i < 10; i++) {// //打印标准位System.out.println(Thread.currentThread().isInterrupted());}});thread.start();thread.interrupt();}
}

结果: 

观察结果可以清晰的看出,打印的全是true,这是因为标志位没有被删除,它的值还是true。

3.5等待一个线程-join() 

方法说明
public void join()等待线程结束
public void join(long millis)等待线程结束,最多等 millis 毫秒
public void join(long millis, int nanos)同理,但可以更高精度
public class testDemo7 {public static void main(String[] args) throws InterruptedException {Thread t1=new Thread(()->{for (int i = 0; i < 10; i++) {System.out.println("第"+i+"次打印"+Thread.currentThread().getName());}System.out.println("----------");});Thread t2=new Thread(()->{for (int i = 0; i < 10; i++) {System.out.println("第"+i+"次打印"+Thread.currentThread().getName());}});t1.start();//t2等待t1执行完毕,t2才可执行t1.join();t2.start();}
}

 结果:

 可以看出使用了join(),两个线程不再是杂乱运行了,而是先运行完t1线程,再运行的t2线程。这就是join 的作用。

3.6休眠线程

这个是比较熟悉一组方法,有一点要记得,因为线程的调度是不可控的,所以,这个方法只能保证实际休眠时间是大于等于参数设置的休眠时间的。

方法说明
public static void sleep(long millis) throws InterruptedException休眠当前线程 millis
毫秒
public static void sleep(long millis, int nanos) throws
InterruptedException
可以更高精度的休眠

3.7 实现一个简单的多线程

 这两个线程任务都是打印自己的名字,其中使用的currentThread()方法是或者当前线程的引用,getName()方法就是或者线程的名字(就算我们没有给线程起名字,系统也会给它自定义一个名字)。

public class testDemo5 {public static void main(String[] args) {Thread t1=new Thread(()->{while (true) {//打印线程名称System.out.println(Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});Thread t2=new Thread(()->{while (true){//打印线程名称System.out.println(Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});//执行线程任务t1.start();t2.start();}
}

代码实现结果:

观察可以看出,两个线程是交叉运行,并且是杂乱运行,好不规律可言。没错,线程的并发就是没有规律的,谁先运行取决于操作系统如何调度线程,因此线程是"抢占式执行"。

4.线程的状态

4.1线程的六种状态 

  • NEW: 安排了工作, 还未开始行动,刚刚创建一个Tread对象,还没开始工作。
  • RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作(正在CPU上执行任务或者在就绪队列中随时可以在CPU上执行的)。
  • BLOCKED: 这几个都表示排队等着其他事情(synchronized加锁)。
  • WAITING: 这几个都表示排队等着其他事情。
  • TIMED_WAITING: 这几个都表示排队等着其他事情(使用sleep或者join方法引起的)。
  • TERMINATED: 工作完成了。

4.2线程状态和状态转移

  举个例子,看下图:

相关文章:

【JaveEE】线程的创建及常见方法解析(Tread类)

目录 1.Tread类介绍 2线程的构造方法——创建线程 1.继承Thread类&#xff0c;重写run()方法 2.使用Runnbable接口创建线程 3.继承 Thread, 重写 run, 使用匿名内部类 4.实现 Runnable, 重写 run, 使用匿名内部类 5.使用 lambda 表达式&#xff08;重点掌握&#xff09;…...

Linux的诞生过程

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。座右铭&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石&#xff0c;故能成其高。个人主页&#xff1a;小李会科技的…...

面部表情识别1:表情识别数据集(含下载链接)

面部表情识别1&#xff1a;表情识别数据集(含下载链接) 目录 面部表情识别1&#xff1a;表情识别数据集(含下载链接) 1.前言 2.表情识别数据集介绍 1.JAFFE数据集 2.KDEF&#xff08;Karolinska Directed Emotional Faces&#xff09;数据集 3.GENKI数据集 4.RaFD数据集…...

CSS实现文字凹凸效果

使用两个div分别用来实现凹凸效果&#xff1b;text-shadow语法 text-shadow: h-shadow v-shadow blur color; h-shadow&#xff1a;必需。水平阴影的位置。允许负值。 v-shadow &#xff1a;必需。垂直阴影的位置。允许负值。 blur&#xff1a;可选&#xff0c;模糊的距离。 co…...

嵌入式常使用的库函数

自己创建简单的mcu中常用的库函数 文章目录自己创建简单的mcu中常用的库函数1. 自己编写库函数的意义2. 计算字符串长度.以\0作为结束符3. 复制字符串4. 字符串比较5. 将整数转换为ASCII数组6. 将ASCII码字符串转换成整数7. 将字节数组转换为16位整数8.计算CRC,用于Modbus协议9…...

【业务安全-02】业务逻辑漏洞之越权操作

越权越权即越权查看被人的信息&#xff0c;又分为水平越权和垂直越权&#xff0c;但是两者的本质都是一样的&#xff0c;只是越权的身份权限不一样而已水平越权&#xff1a;相同级别的用户&#xff0c;如用户A访问用户B垂直越权&#xff1a;普通用户到管理员&#xff0c;普通用…...

完全小白的pycharm深度学习调试+for循环断点条件设置

完全小白的pycharm深度学习调试for循环断点条件设置写在最前面基础方法pycharm断点调试控制台输入代码中循环的debug方法pycharm中图标的介绍常见的BugDebug经验1. 检查激活函数的输入值2. 检查梯度3. 消融实验4. 使用最短的时间5. 静下心来写在最前面 之前把seq2seqattention…...

直方图及其应用

直方图定义直方图是一种描述数据的分布通过将连续变量划分成一系列区间&#xff0c;统计区间频率&#xff0c;并用来表示&#xff0c;以表征其统计特征在图像处理中&#xff0c;直方图可以用来表示图像中像素值的分布状况&#xff0c;描述不同灰度级的像素在图像中的占比直方图…...

《SpringBoot篇》26.SpringBoot整合Jackson超详细教程(附Jackson工具类)

陈老老老板&#x1f9b8;&#x1f468;‍&#x1f4bb;本文专栏&#xff1a;SpringBoot篇&#xff08;主要讲一些与springboot整合相关的内容&#xff09;&#x1f468;‍&#x1f4bb;本文简述&#xff1a;本文讲一下Jackson常见用法&#xff0c;超级详细。&#x1f468;‍&am…...

Redis 如何实现库存扣减操作和防止被超卖?

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…...

(Linux)Ubuntu查看系统版本

uname -a : 查看操作系统的发行版号和操作系统版本 Command: uname -aResult: Linux SERVER 5.19.0-35-generic #36-Ubuntu SMP PREEMPT_DYNAMIC Fri Feb 3 18:36:56 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux uname -v : 查看版本号 Command: uname -vResult: #36-Ubuntu …...

VxWorkds 内存管理(3)

虚拟内存管理 对于带MMU的目标板&#xff0c;VxWorks提供虚拟内存的支持&#xff0c;VxWorks提供了两种虚拟内存管理单元(MMU)的支持: 基本MMU和VxVMI 基本MMU邦定于VxWorks中&#xff0c;可以通过config.h中宏定义INCLUDE MMU BASIC或Tornado工程配置中包含基本MMU组件 VxV…...

单元测试、反射、注解、动态代理

&#x1f3e1;个人主页 &#xff1a; 守夜人st &#x1f680;系列专栏&#xff1a;Java …持续更新中敬请关注… &#x1f649;博主简介&#xff1a;软件工程专业&#xff0c;在校学生&#xff0c;写博客是为了总结回顾一些所学知识点 目录单元测试、反射、注解、动态代理单元测…...

【数据结构】夯实基础|线性表刷题01

作者&#xff1a;努力学习的大一在校计算机专业学生&#xff0c;热爱学习和创作。目前在学习和分享&#xff1a;算法、数据结构、Java等相关知识。博主主页&#xff1a; 是瑶瑶子啦所属专栏: 【数据结构|刷题专栏】&#xff1a;该专栏专注于数据结构知识&#xff0c;持续更新&a…...

Java怎么实现几十万条数据插入(30万条数据插入MySQL仅需13秒)

本文主要讲述通过MyBatis、JDBC等做大数据量数据插入的案例和结果。 30万条数据插入插入数据库验证实体类、mapper和配置文件定义User实体mapper接口mapper.xml文件jdbc.propertiessqlMapConfig.xml不分批次直接梭哈循环逐条插入MyBatis实现插入30万条数据JDBC实现插入30万条数…...

java多线程之线程的六种状态

线程的六种状态(1) NEW(初始状态)(2) TERMINATED(终止状态 / 死亡状态)(3) RUNNABLE(运行时状态)(4) TIMED_WAITING(超时等待状态)(5) WAITING(等待状态)(6) BLOCK(阻塞状态)sleep和wait的区别:操作系统里的线程自身是有一个状态的,但是java Thread 是对系统线程的封装,把这里的…...

UnixBench----x86架构openEuler操作系统上进行性能测试

【原文链接】UnixBench----x86架构openEuler操作系统上进行性能测试 &#xff08;1&#xff09;打开github上 UnixBench 地址&#xff0c;找到发布的tag &#xff08;2&#xff09;找到tar.gz包&#xff0c;右键复制链接 比如这里是 https://github.com/kdlucas/byte-unix…...

于Java8 Stream教程之collect()

目录 前言正文第一个小玩法 将集合通过Stream.collect() 转换成其他集合/数组&#xff1a;第二个小玩法 聚合&#xff08;求和、最小、最大、平均值、分组&#xff09;总结前言 本身我是一个比较偏向少使用Stream的人&#xff0c;因为调试比较不方便。 但是, 不得不说&#…...

Python

1、str 三个关键点&#xff1a; 正着数&#xff0c;0&#xff0c;1&#xff0c;2 反着数&#xff0c;0&#xff0c;-1&#xff0c;-2 str[a&#xff0c;b] 左闭右开 [a&#xff0c;b) str123456789 print(str) # 输出字符串 print(str[0:-1]) # 输…...

Spring框架中IOC和DI详解

Spring框架学习一—IOC和DI 来源黑马Spring课程&#xff0c;觉得挺好的 目录 文章目录Spring框架学习一---IOC和DI目录学习目标第一章 Spring概述1、为什么要学习spring&#xff1f;2、Spring概述【了解】【1】Spring是什么【2】Spring发展历程【3】Spring优势【4】Spring体系…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...