线程的基本操作以及线程的状态

news2024/9/23 13:31:38

目录

🐳今日良言:得之坦然,失之淡然,争取必然,顺其自然。

🐯一、线程的基本操作

🐭1.线程的创建

🐭2.线程的中断

🐭3.线程的等待

🐭4.获取线程实例

🐭5.线程的休眠

🐕二、线程的状态

🐍1.介绍

🐍2.状态之间的切换条件


🐳今日良言:得之坦然,失之淡然,争取必然,顺其自然。

🐯一、线程的基本操作

🐭1.线程的创建

java中创建线程最核心的类:Thread

兄弟们不仅需要认识并熟练掌握这个类,还需要会读哦,来跟博主读  (si  ruan  de)

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

在初学编程时,我们敲的应该都是hello world吧,那么先通过最基本的hello world程序对多线程有一个基本的了解

 当运行这段代码后,输出hello world

分析:

1.t.start()  是线程中的特殊方法,作用是启动(创建)一个线程

2.MyThread 这个类继承Thread 类 并重写了父类的run方法,这个run方法主要是描述了要执行的任务是什么.

3.run方法和start的区别

  start是创建了一个新的线程,操作系统内核创建新的PCB,并且把要执行的指令交给这个PCB,当PCB被调度到CPU上执行的时候,就执行到了线程run方法中的代码了.

   总结:start创建新线程,新线程执行run方法

4.当run方法执行完毕后,新的线程销毁.

上述代码并不能看到并发编程的效果,但是通过下面的代码可以达到并发编程的效果

 执行上述代码,打印出如下结果

 此时可以看出,两个线程(主线程main和新线程)都在执行各自的任务,并没有说一个执行而另外一个不执行,为了让打印速度慢些,可以加入sleep(休眠,后面会详细介绍)

观察执行结果,会发现,打印main和thread是随机出现的,这是为什么呢?

这是因为:操作系统在调度线程的时候,是'抢占式执行',具体哪个线程先上,哪个线程后上是不确定的,这取决于操作系统调度器的具体实现策略.

可能会有老铁疑惑,不是说线程是有优先级的吗?可以通过设置优先级来控制输出顺序吗?

很遗憾,这是不可以的,虽然有优先级,但是在应用程序层面上无法修改,从应用程序(代码)的角度看到的效果好像是线程之间的调度顺序是'随机'的一样,但是操作系统内核里本身并非是随机的,但是干预因素太多,并且应用程序这一层也无法感应到细节,就只能认为是'随机'的.

可以使用JDK自带的工具jconsole查看当前的java程序中的所有线程.

注:运行上面的代码,在运行的时候查看

默认路径如下:

 

 此时点击打开

 

 注:如果有老铁打开jconsole没有运行的程序,此时可以试试右键,管理员方式运行

然后选中这个正在运行的程序点击连接

 点击不安全的连接

 然后选中线程这里,下面的这些就是当前java进程中的所有线程

 

2).实现Runnable接口

3).使用匿名内部类,继承Thread类

4).使用匿名内部类,实现Runnable

5).lambda表达式(最简单)

把任务用lambda表达式来描述,直接把lambda传给Thread构造方法 

 最后再介绍一下Thread的构造方法和一些属性

构造方法

 前两个已经介绍过了,这里说一下后两个,后面两个构造方法就是给创建的线程起一个名字.如下代码

使用jconsole观察

 起别名主要是为了调试的时候便于观察,如果不起别名的话,默认是从Thread-0开始往上加.

常见属性

1).getId()

获取到线程的身份标识.

2).getName()

获取到线程的名字

3).getState()

获取线程的状态,这个在后面线程的状态会详细介绍

4).getPriorit()

获取线程的优先级

5).isDaemon()

判断线程是否为后台线程(守护线程)

 前台线程,会阻止线程结束,前台线程的工作没做完,进程是无法结束的.

 后台线程,不会阻止进程结束,后台线程的工作没做完,进程也是可以结束的.

 在代码中创建的线程都是前台线程,包括main默认也是前台的,其他的jvm自带的线程都是后台的,也可以使用 setDaemon() 方法,将前台线程设置为后台线程.

6).isAlive()

判断当前系统中的这个线程是不是真的存在.

在调用start之前,调用isAlive就是false

在调用start之后,调用isAlive就是true

新线程的run方法还没执行,isAlive()就是false

新线程的run方法正在执行,isAlive()就是true

新线程的run方法执行结束,isAlive()就是false

7).isInterrupted()

判断线程是否被中断,后面会详细介绍

🐭2.线程的中断(终止)

这里的中断,并不是直接让该线程中断,而是通知这个线程:你该中断(终止)了.但是最终是否要终止取决于代码的具体写法.

举例: 博主正在沙发上玩手机,然后老妈告诉在厨房说了一句:儿子,你去把垃圾倒了.此时对于博主而言,有三种选择:

a.立即停止玩手机,直接去倒垃圾.

b.再玩会手机,一会去倒垃圾.

c.假装没听见,不去倒垃圾.

对于线程的终止有如下两种操作

1).使用标志位来控制线程是否要终止.

 此时就可以在主线程中,通过修改flag的值来决定t线程是否结束.运行结果如下

 自定义变量这种方式不能及时响应,尤其是在sleep休眠时间比较长的时候.

2).使用Thread自带的标志位进行判定

如下代码:

 这里的t.interrupt();  就是终止t线程(在main线程中被调用,是main通知t线程终止)

 

此时,运行这段代码,观察运行后的结果

当运行后,会发现,虽然这里报了异常,但是程序还是在执行,这是为什么呢?

这是因为:interrupt做了两件事

a.把线程内部的标志位(boolean)给设置成true.

b.如果线程在进行sleep,就会触发异常,把sleep唤醒.

   但是,当sleep被唤醒后,sleep还会做一件事,将刚刚设置的这个标志位,再设置回false,

   清空了标志位,这就导致了,当异常被catch块捕捉后,循环还要继续执行,所以程序并没有结束.

所以说,调用interrupt,只是通知终止,是否真的终止取决于线程自己(具体的代码)

通过下面三组代码可以更好的理解上面这段话.

为什么sleep要清除标志位呢?

这是因为,当线程被唤醒后,到底是要终止,还是不要终止,是立即终止还是稍后终止,就将选择权交给了程序猿自己.

🐭3.线程的等待

等待线程:就是控制两个线程的执行顺序.

如下代码:

 运行代码,查看结果:

 从运行结果可以看出,当start创建一个新线程后,main线程和t线程继续往下执行,先执行了main线程的打印操作,然后main线程等待t线程先执行,等到t线程执行结束后,再往下执行.main线程等待t线程的时候发生了阻塞(block,常见术语).

t线程肯定是比main线程先结束的.

如果是执行join的时候,t已经结束了,会出现什么情况呢?

此时观察运行结果,会发现,当5s后,main线程立即往下执行,并不会阻塞,这就说明

如果执行join的时候,t线程已经结束, 此时join不会阻塞,会立即返回.

join方法

 第一个不带参数,表示线程A死等线程B,如果线程B不执行结束,线程A一直等

第二个带参数,参数指定一个超时时间(最大等待时间),当线程A等待线程B执行时间超过这个时间的话,线程A不会继续等待线程B,线程A开始执行.

举例:第一种情况

你和你女朋友要出去约会,你女朋友告诉你让你在她家楼下等她,如果见不到女朋友就一直等,'不见不走'.

第二种情况:

你和你女朋友要出去约会,你女朋友告诉你让你在她家楼下等她,你给自己定个等的目标(30min),超过30min就不等了,直接走.(当然这只是一个例子,等还是要等的)

🐭4.获取线程实例

通过静态方法:Thread.currentThread() 返回当前线程对象的引用.

 结合getName() 方法可以观察:

🐭5.线程的休眠

让线程休眠,本质上就是让这个线程不参与调度了(不去CPU上执行了)

在操作系统内核中,有这样一些PCB,构成如下链表:

 在这个链表中的PCB都是就绪状态,这个链表称为就绪队列

PCB并不是使用一个简单的链表来组织的,而是以一系列以链表为核心的数据结构来组织的.

操作系统每次需要调度一个线程去执行,就从就绪队列中选一个就好.

此时,当线程A调用sleep,就会进入休眠状态,将线程A从上述链表中取出,放到另外一个链表中,如下:

这个链表中的PCB都是阻塞状态,暂时不参与CPU的调度执行,将这个链表称为阻塞队列 

 一旦线程进入阻塞状态,对应的PCB就进入阻塞队列了,此时就暂时无法参与调度了.

🐕二、线程的状态

🐍1.介绍

状态是针对当前线程调度的情况来描述的,状态是线程的一种属性,java对于线程的状态进行了细化,主要有以下6种:

1).NEW 

创建了Thread对象,还没调用start,操作系统内核中还没创建对应的PCB

代码观察:

2).TERMINATED

操作系统内核中的PCB执行完毕,线程执行结束,但是Thread对象还在

代码观察:

一旦线程PCB消亡了,此时代码中的t1对象也就没什么用处了,之所以t1对象还存在,是因为java中的对象的生命周期和操作系统内核里的线程并非完全一致,内核的线程释放的时候,无法保证java代码中的t1对象也立即释放,因此,就会存在内核中的PCB没了,但是代码中的t1对象还存在这样的情况,所以就需要通过特定的状态来把t1对象标识为无效.

3).RUNNABLE

可运行的,包括正在CPU上运行的以及在就绪队列中等待去CPU上运行的

代码观察:

 之所以这里能看到RUNNABLE 是因为当前线程run方法里面没写任何sleep之类的方法,当run方法中加上sleep方法时,就可能看到TIMED_WAITING 和 RUNNABLE交替出现,主要出现TIMED_WAITING 还是 RUNNABLE 就取决于t线程运行到哪个环节了.

4).TIMED_WAITING

阻塞状态

观察代码:

通过这里的循环,就能看到这里的交替状态了,当前获取到的状态取决于获取状态的这一瞬间,t1线程处在哪种状态(正在执行,还是sleep)

5).WAITING

阻塞状态

代码观察:

 这里的synchronized 是加锁操作,后续会介绍,这里观察线程的状态即可,t2线程调用wait方法后就处于WAITING状态.

6).BLOCKED

阻塞状态

🐍2.状态之间的切换条件

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

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

相关文章

[附源码]计算机毕业设计学分制环境下本科生学业预警帮扶系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

【POJ No. 3264】区间最值差 Balanced Lineup

【POJ No. 3264】区间最值差 Balanced Lineup 北大OJ 题目地址 其实这道题 之前也做过一次了 http://t.csdn.cn/0YZgC 不过上次是用ST 做的。这次换做 分块来实现。 【题意】 每天挤奶时,约翰的N 头奶牛(1≤N≤50,000)都以相同的顺序排队…

【网络工程】7、实操-万达酒店综合项目(一)

接上篇《6、防火墙介绍及配置实操》 之前我们讲解了防火墙的基础知识以及相应的实操案例,本篇我们结合之前的交换机、路由器及防火墙的知识,进行一个酒店网络项目的实战。 本篇主要介绍一下酒店网络项目的整体需求文档。 一、项目背景 为规范万达美华…

tensorflow fashion_mnist数据集模型训练及预测

✨ 博客主页:小小马车夫的主页 ✨ 所属专栏:Tensorflow 文章目录前言一、环境二、fashion_mnist数据集介绍三、fashion_mnist数据集下载和展示四、数据预处理五、构建模型和训练模型六、模型预测总结前言 前面介绍mnist手写数字集训练,本文对…

自制肥鲨HDO2电源降压延长线,支持3S~6S动力电池

自制肥鲨HDO2电源降压延长线,支持3S~6S动力电池1. 问题源由2. 破题思路2.1 10元大钞搞定2.2 两个毛爷爷搞定3. 解决方案4. 最终延长线产出4.1 裸照4.2 成品5. 花絮1. 问题源由 源由: 电池盒电源线接触不良。 肥鲨眼镜的电源盒问题由来已久,…

SecureCRT隧道,跳板机+端口转发,内网穿透

背景 ServerA(Linux系统): 内网:192.168.111.201 公网:10.121.8.88(虚构的ip方便理解) ServerB: 内网:192.168.111.202 本机: 安装有SecureCRT软件 注意上图中的箭头。箭头指向可…

Android动画——使用动画启动Activity

1、使用动画启动Activity概述 我们在Android开发应用时,会遇到一个页面跳转到另一个页面的情况,这时候我们如果使用动画过渡会使得页面更加的流畅。这是一个滑动式的进入和退出的动画可以看到Android的过渡动画可以在不同状态之间建立视觉联系。您可以为…

find 命令这 7 种高级用法

可以很肯定地说,find 命令是 Linux 后台开发人员必须熟知的操作之一,除非您使用的是 Windows Server。 对于技术面试,它也是一个热门话题。让我们看一道真题: 如果你的 Linux 服务器上有一个名为 logs 的目录,如何删…

MySQL性能调优——索引篇

MySQL为什么会选错索引 使用explain命令可以查看查询语句使用了具体使用了哪个索引,比如 explain select * from t where a between 10000 and 20000;查询结果如图所示。 选择索引是优化器的工作 优化器选择索引的目的是想找到一个最优的执行方案,并…

08_线程池

08_线程池前言Callable接口ThreadPoolExecutor**为什么用线程池****线程池的好处**架构说明创建线程池底层实现线程池的重要参数拒绝策略线程池底层工作原理问题二: 线程池使用过吗?谈谈在生产上如何设置的参数?线程池的拒绝策略你谈谈?工作中单一的/固定数的/可变数的三种创…

设计模式 之 行为型模式

设计模式 之 行为型模式 模式 & 描述包括行为型模式 这些设计模式特别关注对象之间的通信。责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern)解释器模式(Interpreter Pattern)…

Web 性能指标

Web 性能指标 对于 Web 开发人员来说,如何衡量一个 Web 页面的性能一直是一个难题。 最初,我们使用 Time to First Byte、DomContentLoaded 和 Load 这些衡量文档加载进度的指标,但它们不能直接反应用户视觉体验。 为了能衡量用户视觉体验…

[附源码]计算机毕业设计springboot志愿者服务平台

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

[数据结构]八大排序算法总结

作者: 华丞臧专栏:【数据结构】 各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞收藏关注)。如果有错误的地方,欢迎在评论区指出。推荐一款刷题网站 👉 LeetCode刷题网站 目录 一、排序的概念及其运用 1.1排…

【目的:windows下VS2017/2022配置使用opengl - 初探-创建一个空窗口】

目的:windows下VS2017/2022配置使用opengl - 初探-创建一个空窗口 环境: 系统:Win10 环境:VS2017 64bit步骤: windows下visualstudio下使用opengl,搭建配置环境并测试窗口 1、opengl库,vs下自…

Crack:Open Inventor 10.12.1 Fixed Bugs List 10.12

10.12.0 - 10.12.1 Open Inventor 10.12.1 Core #OIV-4245 Shapes not rendered with MultipleInstancing  #OIV-4258 Transparency issue with SoPackedColor – CAS-41256-F0S4 OivSuite.Java #OIV-4273 Memory leak with RemoteViz Java and JVM VolumeViz #OI…

CMake中add_library的使用

CMake中的add_library命令用于使用指定的源文件向项目(project)中添加库&#xff0c;其格式如下&#xff1a; add_library(<name> [STATIC | SHARED | MODULE][EXCLUDE_FROM_ALL][<source>...]) # Normal Libraries add_library(<name> OBJECT [<source&…

【Java 快速复习】垃圾回收算法 垃圾回收器

快速理解 Java 垃圾回收算法 & 垃圾回收器 先说个关系概念&#xff0c;垃圾回收的算法是逻辑概念的定义&#xff0c;用于规范垃圾回收器实现方的一些行为&#xff0c;而垃圾回收器就是实现这些算法的工具&#xff0c;这些工具大概是一系列的 C 的类以及其实现的一些对应回…

Linux服务器上跑深度学习实验

原文地址&#xff1a;Linux上跑深度学习实验 目录远程连接环境搭建与服务器断开连接后代码停止之前一直使用Google Colab跑实验&#xff0c;因为实验的规模不大&#xff0c;配合Google Drive用起来就很舒服&#xff0c;但是最近要系统地进行实验&#xff0c;规模一下子上来了&a…

【Spring】一文带你搞懂Spring容器配置

前言 本文为大家介绍的是Spring容器配置相关知识&#xff0c;包含Bean和Configuration的使用&#xff0c;使用 AnnotationConfigApplicationContext实例化Spring容器&#xff0c;Bean注解的使用&#xff0c;Configuration的使用&#xff0c;Import 注解的使用&#xff0c;结合J…