Thread类和线程状态

news2024/11/22 22:13:31

目录

Thread 的常见构造方法

Thread 的几个常见属性

经典面试题:start和run的区别

interrupt 线程中断

join 线程等待

currentThread 获得当前这个线程对应的 Thread 对象的引用。

sleep 置顶休眠的时间(阻塞一会)

sleep(1000),真的只是休眠1000毫秒吗?

线程状态


我的GitHub:Powerveil · GitHub

我的Gitee:Powercs12 (powercs12) - Gitee.com

皮卡丘每天学Java

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关 联。

Thread 的常见构造方法

方法说明
Thread()创建线程对象
Thread(Runnable targer)使用 Runnable 对象创建线程对象
Thread(String name)创建线程对象,并命名
Thread(Runnable target, String name)使用 Runnable 对象创建线程对象,并命名
Thread(ThreadGroup group, Runnable target)线程可以被用来分组管理,分好的组即为线程组,了解即可
 Thread t1 = new Thread();
 Thread t2 = new Thread(new MyRunnable());
 Thread t3 = new Thread("这是我的名字");
 Thread t4 = new Thread(new MyRunnable(), "这是我的名字");

Thread 的几个常见属性

属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台线程(守护线程)isDaemon()
是否存活isAlive()
是否被中断isInterrupted()
  • ID 是线程的唯一标识,不同线程不会重复

  • 名称是各种调试工具用到

  • 状态表示线程当前所处的一个情况,下面我们会进一步说明

  • 优先级高的线程理论上来说更容易被调度到

  • 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。

  • 是否存活,即简单的理解,为 run 方法是否运行结束了

  • 线程的中断问题,下面我们进一步说明

注意:

这里的 id 是 Java 中给 Thread 对象安排的 身份标识,和操作系统内核中的 PCB 的 pid,以及和操作系统提供的线程 API 中的 线程id 都不是一回事。 身份标识可以有多个,在不同的环境下,使用不同的标识。

一个线程:

  1. 在 JVM 中有个 id

  2. 在操作系统的进程 API 有个 id

  3. 内核 PCB 中还有个 id

这三个 id 效果一样,但是在不同的环境下使用。

后台线程(守护线程)

这里的Daemon(守护),

默认创建的线程是“前台线程” 前台线程会阻止进程退出,如果 main 运行完了,前台线程还没完,进程不会退出。

如果是后台线程,后台线程不阻止进程退出,如果 main 等其他的前台线程执行完了,这个时候,即使后台线程没执行完,进程也会退出

前台线程可以有很多个(main 也是一个前台线程)

后台线程也可以有很多(GC 也是一个后台线程)

线程是否存活 isAlive 判定内核的线程在不在

Thread 对象 虽然和内核中的线程是一一对应的关系,但是生命周期并非完全相同

Thread 对象出来了,内核里的线程还不一定有,调用 start 方法,内核线程才有,当内核里的线程执行完了(run 运行完了),内核的线程就销毁了,但是 Thread 对象还在

调用 start 才会真正创建线程,不调用 start 没创建线程(在内核里创建 PCB)

经典面试题:start和run的区别

直接调用 run 并没有创建线程,只是在原来的线程中运行的代码 调用 start 则是创建了线程,在新线程中执行代码(和原来的线程是并发的)

interrupt 线程中断

run 方法执行完了,线程就结束了,有没有办法,让线程提前一点结束呢? 就是通过线程中断的方式来进行(本质仍然是让 run 方法尽快结束,而不是 run 执行一半,强制结束) 这就取决于 run 里面的具体是如何实现的了

1.直接自己定义一个标志位,作为线程是否结束的标记

 public class Demo10 {
     private static boolean isQuit = false; // 自定义标志位
     public static void main(String[] args) {
         Thread t = new Thread(() -> {
             while (!isQuit) {
                 System.out.println("hello thread");
                 try {
                     Thread.sleep(1000);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
             }
             System.out.println("t 线程执行完了");
         });
 ​
         t.start();
 ​
         try {
             Thread.sleep(3000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
 ​
         isQuit = true;
         System.out.println("设置让 t 线程结束!");
     }
 }

2.还可以使用标准库里面自带的一个标志位

Thread.currentThread().isInterrupted()

在主线程中,通过 t.interrupt() 来中断这个线程,设置标志位 true

 public class Demo11 {
     public static void main(String[] args) {
         Thread t = new Thread(() -> {
             while (!Thread.currentThread().isInterrupted()) {
                 System.out.println("hello thread");
                 try {
                     Thread.sleep(1000);
                 } catch (InterruptedException e) {
                     // e.printStackTrace();
 ​
                     // [方式一] 立即结束线程
                     break;
 ​
                     // [方式二] 啥都不做, 不做理会. 线程继续执行
 ​
                     // [方式三] 线程稍后处理
                     // Thread.sleep(1000);
                     // break;
                 }
             }
             System.out.println("t 线程执行完了");
         });
 ​
         t.start();
 ​
         try {
             Thread.sleep(3000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
 ​
         t.interrupt();
         System.out.println("设置让 t 线程结束!");
     }
 }

interrupt 方法的行为有两种情况

  1. t 线程在运行状态会设置

    Thread.currentThread().isInterrupted()

    标志位为 true

  2. t 线程在阻塞状态 (sleep)

    不会设置标志位,而是触发一个InterruptedException

    这个异常会发 sleep 提前唤醒

第一种情况,直接中断循环

 

 

第二种情况:打断sleep,但是没有结束循环

 

在 Java 中,中断线程并非是强制的,由 线程自身的代码 来进行判定处理的

线程自身能怎么处理呢?

  1. 立即结束线程

  2. 不理会

  3. 稍后理会

却决于代码怎么写

join 线程等待

线程之间的调度顺序,是不确定的 但是可以通过一些特殊操作来对线程的执行顺序做出干预,其中 join 就是一个办法,控制线程之间的结束顺序

 public class Demo {
     public static void main(String[] args) {
         Thread t = new Thread(() -> {
             for (int i = 0; i < 5; i++) {
                 System.out.println("hello power!");
                 try {
                     Thread.sleep(1000);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
             }
         });
         t.start();
 ​
         System.out.println("main 线程 join 之前");
         try {
             t.join();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         System.out.println("main 线程 join 之后");
     }
 }

 

如果调用 join 之前,线程已经结束了,此时 join 不需要阻塞等待

join 方法还可以带一些参数

public void join(long millis)

public void join(long millis, int nanos)

这两个是带时间的等待,过时不候。millis(毫微秒),nanos(纳米级)

currentThread 获得当前这个线程对应的 Thread 对象的引用。

哪个线程里面调用,得到的就是哪个线程的引用

sleep 置顶休眠的时间(阻塞一会)

操作系统管理这些 线程的 PCB 的时候,是有多个链表的

 

Thread-0调用 sleep 方法

 

sleep结束

 

当 Thread-0线程的sleep 的时间到了,就会被移动会之前的就绪队列 挪回了就绪队列,不代表立即就能够在 CPU 上执行,还得看系统啥时候调度到这个线程

sleep(1000),真的只是休眠1000毫秒吗?

不一定,一般是要略微多于 1000毫秒的,具体多少就看调度的时间开销了 快则(<1ms),慢则多好几毫秒

通常的操作系统(Windows,Linux,MacOS),调度开销都是不可预期的,也可能很快,也可能很慢。

有些场景不希望这个调度开销太大,速度太慢(比如发射卫星),如果因为火箭系统里面任务调度开销对时间产生误差,结果就是灾难性的。

因为为了解决上述问题,还有一类操作系统,叫做 “实时操作系统”,特点就是任务调度的开销是可预期的(做实时,是要付出一些代价的)

比较有名的“实时操作系统”是vxworks

线程状态

在操作系统中,对于 PCB 有一个状态的描述 Java 中觉得自身的状态不是特别合适,自己又搞了一台状态规则

  • NEW:Thread 对象创建来了,但是 内核的 PCB 还没创建(还没有真正创建线程)

  • TERMINATED:内核的 PCB 销毁了,但是 Thread 对象还在

  • RUNNABLE:就绪状态(正在 CPU 上运行 + 在就绪队列中排队)

  • TIMED_WAITING:按照一定的时间,进行阻塞,sleep

  • WAITING:特殊的阻塞状态,调用 wait

  • BLOCKED:等待锁的时候进入的阻塞状态

整体来说,状态分为 就绪 + 阻塞(分成三种具体情况了)

 

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

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

相关文章

使用 MindStudio进行基于 MindX SDK 辅助驾驶项目的开发

视频链接&#xff1a;https://www.bilibili.com/video/BV1K8411p7Cm/ 1 任务介绍 ASSISTED-DRIVING的中文含义为辅助驾驶&#xff0c;其先采用了yolov3模型将图片中的交通标志检测出来&#xff0c;然后利用resnet18模型获对检测出来的交通标志进行分类&#xff1b;在道路线分…

0-1规划下的数独问题

数独显然是一个0-1规划问题.虽然这个什么凸分析还是啥的分析有这个优化的方法,但是,你DFS也不是完全一点不可能的对吧.嗯,既然这样的话,我们就要去解决这样一个更细致的问题了.数独这个问题他的解的存在性,唯一性怎么样.当然,已经有结论了,一个9*9的数独至少要给出17个值才能约…

Qt扫盲-QGridLayout理论总结

QGridLayout理论总结1. 简介2. 操作布局元素3. 常用属性4. 间隔设置1. 简介 QGridLayout 占用来自其父布局或 parentWidget()获得的空间&#xff0c;将其划分为行列表格形式&#xff0c;在每个布局的表格里放置控件或者布局器就行。 一般来说&#xff0c;列和行的行为功能相同…

Sourcetree安装详细步骤

前言&#xff1a; Sourxetree 作为 免费的 Git 客户端工具&#xff0c;有许多优点。Sourcetree 简化了与Git存储库交互的方式&#xff0c;因此我们可以专注于编码。通过 Sourcetree 简单又快捷的管理我们 的存储库。 下载安装包 进入 官网 选择Windows系统的安装包 &#xff…

【大数据技术Hadoop+Spark】HDFS Shell常用命令及HDFS Java API详解及实战(超详细 附源码)

需要源码请点赞关注收藏后评论区留言私信~~~ 一、HDFS的Shell介绍 Shell在计算机科学中俗称“壳”&#xff0c;是提供给使用者使用界面的进行与系统交互的软件&#xff0c;通过接收用户输入的命令执行相应的操作&#xff0c;Shell分为图形界面Shell和命令行式Shell。 文件系统…

PTC Creo Illustrate生产技术设备

PTC Creo Illustrate生产技术设备 Creo Illustrator是一款适用于生产技术设备的软件。该软件将三种功能与当前CAD设计数据、技术规范以及所需和可能使用的各种部件相结合。这些工具对供应商和客户尤其有用。供应商可以使用本文档中提供的信息熟悉机器。查看内部零件&#xff0c…

YOLO系列目标检测算法——YOLOR

YOLO系列目标检测算法目录 - 文章链接 YOLO系列目标检测算法总结对比- 文章链接 YOLOv1- 文章链接 YOLOv2- 文章链接 YOLOv3- 文章链接 YOLOv4- 文章链接 Scaled-YOLOv4- 文章链接 YOLOv5- 文章链接 YOLOv6- 文章链接 YOLOv7- 文章链接 PP-YOLO- 文章链接 …

喜讯 | 美格智能子公司美格智联成功获选2022年首批国家级“高新技术企业”认定

近日&#xff0c;全国高新技术企业认定管理工作领导小组办公室发布了关于对深圳市认定机构2022年认定的第一批高新技术企业进行备案公示的通知&#xff0c;根据《高新技术企业认定管理办法》&#xff08;国科发火〔2016〕32号&#xff09;和《高新技术企业认定管理工作指引》&a…

[C/C++/初学者]500以内的亲密数对(VS2012)

在开始编写程序之前&#xff0c;我们需要了解一个东西。 何为亲密数对&#xff1f; 简单来说&#xff0c;就是数a的正因子数&#xff08;除本身外&#xff09;等于数b的正因子数&#xff08;除本身外&#xff09;。 符合这项条件的两个数&#xff0c;我们称他们为亲密数对。 …

[附源码]Python计算机毕业设计高校体育馆管理信息系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

146.个性化推荐系统案例介绍

YouTube的推荐系统算法由两个神经网络组成&#xff1a; 一个用于候选生成一个用于排序 以用户的浏览历史为输入&#xff0c;候选生成网络可以显著减小可推荐的视频数量&#xff0c;从庞大的库中选出一组最相关的视频 这样生成的候选视频与用户的相关性最高&#xff0c;然后会对…

【ROS话题通信】发布者和订阅者

前言 本文记录ROS话题通信的学习过程&#xff0c;便于后续复习。首先明确&#xff0c;ROS中的话题通信&#xff0c;在ROS通信中非常重要&#xff0c;实现了分布式发布接收消息&#xff0c;也是实现了不同编程语言间的解耦&#xff0c;下面记录下自己学习过程中的相关代码和配置…

Kotlin小菜——基础语言教程

概述 Kotlin是JetBrains推出的一种编程语言&#xff0c;JetBrains是最智能的Java IDE的官方设计器&#xff0c;名为Intellij IDEA。这是在JVM上运行的强静态类型语言。2017年&#xff0c;谷歌宣布Kotlin是Android开发的官方语言。Kotlin是一种开源编程语言&#xff0c;它将面向…

会话Cookie跟踪技术

会话 用户打开浏览器&#xff0c;访问web服务器的资源&#xff0c;会话建立&#xff0c;直到有一方断开连接&#xff0c;会话结束。在一次会话中可以包含多次请求和响应。 从浏览器发出请求到服务端响应数据给前端之后&#xff0c;一次会话(在浏览器和服务器之间)就被建立了 …

产品设计:Material Design 学习笔记二

​5、图标 桌面图标 桌面图标尺寸是48dp X 48dp。 桌面图标建议模仿现实中的折纸效果&#xff0c;通过扁平色彩表现空间和光影。注意避免以下问题&#xff1a; ①不要给彩色元素加投影 ②层叠不要超过两层 ③折角不要放在左上角 ④带投影的元素要完整展现&#xff0c;不能…

Debug怎么用

文章目录前言一、打断点运行Debug二、页面重新运行功能三、回到代码看断点前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 因为最近有个项目注册不好使&#xff0c;想看看哪的问题&#xff0c;所以用debug看看程序走到了哪 提示&#xff1a;以下是本篇文…

docker部署mysql初始化数据库

一、前言 在使用docker部署mysql服务时&#xff0c;往往需要在创建容器时新建database&#xff0c;在需要在创建实例的过程中希望初始化sql脚本。 mysql官方镜像支持在容器初次启动时自动执行指定的sql脚本或shell脚本&#xff08;注意&#xff1a;只有初次启动时才能自动执行&…

【正点原子I.MX6U-MINI】通过tftp从Ubuntu中下载zImage 和设备树文件 | 从网络启动Linux系统

从网络启动linux系统的唯一目的就是为了调试&#xff01;不管是为了调试linux系统还是linux下的驱动。每次修改linux系统文件或者linux下的某个驱动以后都要将其烧写到EMMC中去测试&#xff0c;这样太麻烦了。我们可以设置linux从网络启动&#xff0c;也就是将 linux 镜像文件和…

【OpenCV-Python】教程:5-3 光流

OpenCV Python Optical Flow (光流) 【目标】 了解光流的概念和用 Lucas-Kanade 算法估计光流我们将使用cv2.calcOpticalFlowPyrLK()这样的函数来跟踪视频中的特征点。们将使用cv2.calcOpticalFlowFarneback()方法创建一个密集的光流场&#xff0c;可以用于前景检测。 【理论…

[附源码]Python计算机毕业设计高校心理咨询管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…