JavaEE——简单介绍Thread类以及线程的基本操作

news2025/7/15 22:56:19

文章目录

  • 一、Thread 类中的常见构造方法
  • 二、Thread 的一些常见属性
  • 三、线程的启动——start()
    • isAlive() 方法的解释
  • 四、线程中断
  • 五、线程等待-join()了解
  • 六、简单解释线程休眠

一、Thread 类中的常见构造方法

我们已知,Thread 类是Java中多线程中的一个关键类,因此我们需要知道其较为常用的构造方法,如下图:

在这里插入图片描述

Thread t1 = new Thread();	//创建一个线程对象
Thread t2 = new Thread(Runnable());	//实现Runnable接口中的方法
Thread t3 = new Thread(String name);	//创建线程对象并且命名
Thread t4 = new Thread(Runnable(),String name);		//使用Runnable 接口实现线程对象并且重命名

简单实现最后一种形式的代码:

public class ThreadDemo {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable(){
            public void run(){
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("hello");
                }
            }
        },"myThread");
        t.start();
    }
}

运行程序,打卡我们的 jconsole 找到我们的 ThreadDemo 线程,连接后就会找到我们自己命名的线程,如下图:
在这里插入图片描述

二、Thread 的一些常见属性

在这里插入图片描述

  • ID 是线程的唯一标识,每一个线程都有对应的id
  • 名称 是指在构造方法中自己起的名称,调试时使用
  • 状态 状态标识线程当前所处的一种情况
  • 优先级 可以用该方法来获取设置优先级,优先级较高的理论上更容易被调度(其实用处不大)
  • 是否后台线程 对于后台线程,JVM 会在一个进程的所有非后台线程结束后,才会结束运行。
    前台线程:会阻止进程的结束,前台线程的工作未完成,进程就不会结束。
    后台线程:不会阻止进程的结束,后台线程如果未完成,而前台线程完成,进程依然可以照常结束。
  • 是否存活:简单理解,就是指“run”方法是否结束。

代码解释后台线程

    public static void main(String[] args) {
        Thread t = new Thread(()->{
            while(true){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("hello");
            }
        });
        //将线程设定为后台线程
        t.setDaemon(true);
        t.start();
        System.out.println("main");
        //判断 t 线程是否为后台线程
        System.out.println("t线程是否为后台线程:"+t.isDaemon());
    }

在这里插入图片描述

三、线程的启动——start()

到目前为止,我们已知可以通过重写 run 方法来创建一个线程对象,但是,线程对象的创建并不意味着线程就可以开始运行。
因此,我通过下面的一个图示来给大家详细解释其中原因:
在这里插入图片描述

isAlive() 方法的解释

通过上面的解释我们不难理解,线程的存在与否和线程的开始与否有着密切的关系

因此,我们可以大致进行设想会出现下面的情况:

  • 在 start() 方法前,线程不存在显示 false
  • 在线程运行中,线程正在进行显示 true
  • 在线程任务结束后显示 false

有了以上的设想,我们就可以通过编写相应的代码进行验证:

    public static void main(String[] args) {
        Thread t = new Thread(()->{
            try {
                //设置线程等待,延长线程时间
                Thread.sleep(100);
                System.out.println("hello Thread!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        //start 方法之前,对线程判断
        System.out.println(t.isAlive());
        t.start();
        //start 后,线程运行中,对线程判断
        System.out.println(t.isAlive());
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 通过等待,线程运行完毕
        System.out.println(t.isAlive());
    }

运行截图如下:
在这里插入图片描述

这里我实现了设想的三种情况,不难发现符合预期。

总结: 只有调用了 start 方法线程才算正真的从操作系统的底层中被创建出来!

四、线程中断

所谓线程中断,顾名思义,就是让线程在正常运行时因为某些原因需要让其暂停运转,但是,这里的中断,并不是表示让线程立即停止,而只是通知线程,你应该停止了。至于线程是否停止,这取决于代码本身的写法!

  1. 通过程序员自己设置标志位来终止代码

代码实现:

    private static boolean flag = true;
    public static void main(String[] args) throws InterruptedException {
        //中断一个线程
        Thread t = new Thread(() -> {
            while(flag){
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();

        Thread.sleep(3000);
        //在主线程里就可以随时通过 flag 变量的取值,来操作 t 线程是否结束
        flag = false;
    }

这里的代码就可以解释要让一个线程停止,什么时候停止,全部都是由代码内部来实现的。
注:但是,这种方法存在很大的缺陷,在我们运行代码时就会发现,程序停止时中间会有一个很大的空档期,这就说明自定义变量这种方式反应较慢,尤其是在 sleep 时间较长时,不能做到及时响应。

  1. 使用 Thread 自带的标志位来终止代码
  • 使用 Thread 对象中的 interrupted() 方法来通知线程的结束

代码展示:

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
        //1.while中的语句需要注意
            while(!Thread.currentThread().isInterrupted()){
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        Thread.sleep(3000);
	//2.调用 interrupt 方法告知程序应该结束了
        t.interrupt();
    }

解释 while 语句中的代码,如图:

在这里插入图片描述

解释 2 处的引用:

即,就是重新设定 Boolean 变量告知线程应该停止。

对于代码整体的运行逻辑进行解释

在这里插入图片描述
其实不难发现,这种方法就是将第一种 自定义标志位 的 boolean 操作封装到 Thread 的一个类当中了。
运行结果:
在这里插入图片描述
如图所示,我们不难发现,这段代码直接印证了 线程中断,并不是让线程立即停止,而是告诉线程应该停止了 这句话。

到此,我们需要知道 interrupt 会做以下两件事:

  1. 将线程内 标志位(boolean) 给设置成 true。
  2. 如果线程正在进行 sleep ,此时就会触发异常,将 sleep 唤醒。
    但是,sleep 在唤醒的时候,会将刚才设置的标志位再设定位 false(即,清空标志位)

所以通过以上两点,我们可以更加明确地知道为何在 sleep 报错后,循环仍在继续!

自己设定让线程相应终止请求

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while(!Thread.currentThread().isInterrupted()){
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    //要实现线程的及时响应,只需要添加 break 即可
                    //此处可以根据需要添加任意的代码
                    break;
                }
            }
        });
        t.start();
        Thread.sleep(3000);

        t.interrupt();
    }

在这里插入图片描述

五、线程等待-join()了解

在生活中,我们在协同作业的时候常常会遇到等待同伴的情况,线程中也是如此,因此我们也需要一些相应方法来满足需求。

join 的部分相关方法与说明
在这里插入图片描述
代码示例:

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            for (int i = 0; i < 3; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // getname()获取自己起的名称
                System.out.println(Thread.currentThread().getName()+"正在工作");
            }
        });

        Thread t1 = new Thread(t,"李四");
        Thread t2 = new Thread(t,"张三");
        t1.start();
        // 让 t1 先执行,主线程 main 先等待
        t1.join();
        System.out.println("李四完成工作,张三开始");
        t2.start();
        //让 t2 先执行,主线程 main 先等待
        t2.join();
        System.out.println("张三完成任务");
    }

运行结果
在这里插入图片描述

六、简单解释线程休眠

通过前面的许多代码,我相信大家对 sleep() 这个方法的使用并不陌生,下面,我就深入到操作系统内核中来给大家解释一下,线程休眠到底是如何运行做的。

所谓线程休眠,即,就是让此线程不参与调度,不到 CPU 上执行。
相关解释如下图:

在这里插入图片描述
需要注意的是,虽然 sleep 方法设定了阻塞时间,但是实际情况要比设定的时间间隔大,因为需要考虑到唤醒后调度的开销,因为对应的线程在唤醒后是无法在第一时间就被调用到 CPU 上执行的!

到此, 文章结束, 如有不足, 欢迎提出. 如有错误, 欢迎指正!

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

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

相关文章

MATLAB的快速入门

第一部分&#xff1a;基础知识常用命令&#xff1a;clc %清除命令行窗口 clear %清空工作区数据 cd %显示或改变工作目录 clf %清除图形窗口 help %打开帮助文档 save %保存内存变量到指定文件 hold %保持图形 close %关闭当前图窗 quit %退出变量&#x…

sentry权限控制

sentry权限控制 文章目录sentry权限控制前言1. 安装2. hive内得配置4. hdfs配置5. Hue 授权6. 连接hive配置权限7. 验证前言 Apache Sentry是一个可以对Hadoop集群中的数据及元数据进行细粒度管理的权限管理系统。Sentry目前可以与ApacheHive&#xff0c;HiveMetastore / HCat…

前端基础(十四)_Math对象

Math对象 1.Math对象 对象.方法名 (1)Math.floor() 向下取整 去掉小数部分 等同于parseInt Math.floor(1.222) //1(2)Math.ceil() 向上取整 去掉小数部分 向上进一 Math.ceil(1.222) //2(3)Math.round() 四舍五入 4.5 5 针对小数点后面第一位数字 Math.round(1.272) //1 Ma…

嵌入式安防监控项目——exynos4412主框架搭建

目录 一、模块化编程思维 二、安防监控项目主框架搭建 一、模块化编程思维 其实我们以前学习32使用keil的时候就是再用模块化的思维。每个硬件都单独有一个实现功能的C文件和声明函数&#xff0c;进行宏定义以及引用需要使用头文件的h文件。 比如简单的加减乘除取余操作我们…

Spark Standalone 部署

Spark Standalone 部署解压缩文件修改配置文件启动集群Web UI 界面提交应用提交参数说明配置历史服务配置日志存储路径添加日志配置重启重新执行任务查看历史服务配置高可用&#xff08;HA&#xff09;集群规划停止集群启动 Zookeeper启动集群关闭集群关闭历史服务解压缩文件 …

Go语言使用Playwright自动化测试、录屏、执行js

Go版本的Playwright支持Chromium、Firefox和WebKit的Web自动化测试&#xff0c;兼容Windows、Linux和MacOS&#xff0c;默认支持headless无头模式&#xff0c;安装方便、绿色高效、兼容性强、运行速度快。 支持的主要功能有&#xff1a; 跨多个页面、域名和iframe的场景&#x…

什么led灯性价比高?家用led灯选哪种最好

人造灯具经过多年的发展&#xff0c;现在最为成熟的工艺就是led灯了&#xff0c;不仅有荧光灯高效节能、省电高亮的特点&#xff0c;而且光线可控性非常高&#xff0c;对于调光、提高光线柔和度等方面非常方便&#xff0c;保护眼睛更有效。 那么什么led灯性价比高呢&#xff0c…

JavaScript 高级5 :ES6

JavaScript 高级5 &#xff1a;ES6 Date: January 19, 2023 Sum&#xff1a;ES6新增语法、ES6内置对象扩展&#xff08;Array、String扩展方法、set数据结构&#xff09; 目标 能够说出使用let关键字声明变量的特点 能够使用解构赋值从数组中提取值 能够说出箭头函数拥有的…

基于SpringBoot的学生会管理系统 源码

StudentUnionManagementSystem 基于SpringBoot的学生会管理系统 源码 链接 目录StudentUnionManagementSystem介绍软件架构使用说明1.页面登录2.首页3.成员信息管理4.角色信息管理5.权限管理6.活动管理7.文件管理8.活动展示介绍 学生会管理系统 SpringBoot Mybatis-plus shir…

CentOS 7 怎样设置自动连接网络

作为 Linux 中的重要一员&#xff0c;CentOS 7 始终把安全放在第一位&#xff0c;开机以后并不会自动启动网络。而且&#xff0c;相比 Windows 下只需点击几下鼠标便能搞定配置&#xff0c;在 CentOS 7 中要想设置开机自动连接网络&#xff0c;简直可以说是需要具有“专业级水准…

手动实现 数组和链表

数组和链表示意图 目的 不用java标准库 自己时间 一个 arraylist 和 linked list 区别 数组 数组 支持 随机访问 可以立即访问 根据 第一个元素的位置&#xff0c; 推算出 第三个地方的位置 如下图所示&#xff0c;假设我们知道 头的位置是X 数组是 int类型 每个位置就是 …

Qt音视频开发21-mpv内核万能属性机制

一、前言 搞过vlc内核后又顺带搞了搞mpv内核&#xff0c;mpv相比vlc&#xff0c;在文件数量、sdk开发便捷性方面绝对占优势的&#xff0c;单文件&#xff08;可能是静态编译&#xff09;&#xff0c;不像vlc带了一堆插件&#xff0c;通过各种属性来set和get值&#xff0c;后面…

第十四届蓝桥杯三月真题刷题训练——第 5 天

目录 题目1&#xff1a;数的分解 题目描述 运行限制 代码&#xff1a; 题目2&#xff1a;猜生日 题目描述 运行限制 代码&#xff1a; 题目3&#xff1a;成绩分析 题目描述 输入描述 输出描述 输入输出样例 运行限制 代码&#xff1a; 题目4&#xff1a;最大和…

Vue3做出B站【bilibili】 Vue3+TypeScript【快速入门一篇文章精通系列(一)前端项目案例】

本项目分为二部分 1、后台管理系统&#xff08;用户管理&#xff0c;角色管理&#xff0c;视频管理等&#xff09; 2、客户端&#xff08;登录注册、发布视频&#xff09; Vue3做出B站【bilibili】 Vue3TypeScript【快速入门一篇文章精通系列&#xff08;一&#xff09;前端项目…

vue3 拖拽 穿梭框

文章目录期望结果当前技术栈实现方法安装 sortablejs导入 sortablejs视图 通过 id 绑定 sortablejs 数据通过 data-xxx 自定义属性 挂载ts中 通过id获取dom 实现拖拽 getNewArr函数通过自定义属性对数据做处理以下是全部代码官网链接下面是文档UsageOptionsgroup optionsort op…

代码随想录之哈希表(力扣题号)

242. 有效的字母异位词 直接用数组模拟哈希表 只有小写字母&#xff0c;开26的数组就可以了 class Solution {public boolean isAnagram(String s, String t) {//24-28int[] hash new int[26];Arrays.fill(hash,0);for(int i0;i<s.length();i){hash[s.charAt(i)-a];}for(i…

2023年3月全国数据治理工程师认证DAMA-CDGA/CDGP火热报名中...

弘博创新是DAMA中国授权的数据治理人才培养基地&#xff0c;贴合市场需求定制教学体系&#xff0c;采用行业资深名师授课&#xff0c;理论与实践案例相结合&#xff0c;快速全面提升个人/企业数据治理专业知识与实践经验&#xff0c;通过考试还能获得数据专业领域证书。 DAMA认…

【致敬女神】HTMLReport应用之Unittest+Python+Selenium+HTMLReport项目自动化测试实战

HTMLReport应用之UnittestPythonSeleniumHTMLReport项目自动化测试实战1 测试框架结构2 技术栈3 实现思路3.1 使用HtmlTestRunner3.2 使用HTMLReport4 TestRunner参数说明4.1 源码4.2 参数说明5 框架代码5.1 common/reportOut.py5.2 common/sendMain.py5.3 report5.3.1 xxx.htm…

ARM架构下使用Docker安装Nacos

大家好&#xff0c;我是中国码农摘星人。 欢迎分享/收藏/赞/在看&#xff01; 注意&#xff1a;以下内容仅适用于 ARM 架构&#xff0c;X86 及 AMD 架构理论类似&#xff0c;只需要修改配置即可。 构建 MySQL 8.x 镜像 MySQL 5.x 版本没有 ARM 架构的镜像 FROM mysql:8.0.32 A…

Java 8 排序

今天分享 Java 8 进行排序的 10 个姿势&#xff0c;其实就是把 Java 8 中的 Lambda、Stream、方法引用等知识点串起来 传统排序 现在有一个 List 集合&#xff1a; public static List<User> LIST new ArrayList() {{add(new User("Lisa", 23));add(new Us…