【JavaEE初阶】 Thread类及常见方法

news2024/11/25 18:37:16

文章目录

  • 🌴Thread类的概念
  • 🌳Thread 的常见构造方法
  • 🎄Thread 的几个常见属性
  • 🍀start()-启动一个线程
  • 🌲中断一个线程
    • 🚩实例一
    • 🚩实例二
    • 🚩实例三
  • 🎍join()-等待一个线程
    • 🚩获取当前线程引用
    • 🚩休眠当前线程
  • ⭕总结

🌴Thread类的概念

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

每个执行流,也需要有一个对象来描述,类似下图所示,而 Thread 类的对象就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理
在这里插入图片描述

🌳Thread 的常见构造方法

在这里插入图片描述
使用如下:

Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("这是我的名字");
Thread t4 = new Thread(new MyRunnable(), "这是我的名字");

命名操作:

  • 是将你在使用 jconsole 命令观察线程时的看到的线程名改为你自己的重命名

比如有以下程序:

public class Test1 {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            while (true) {
                System.out.println("我的名字叫遇事问春风乄");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"遇事问春分乄");
        thread.start();
        while (true) {
            System.out.println("我的名字叫main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

当我们用 jconsole 命令进行查看时,结果如下:
在这里插入图片描述
上面就会有我们自己的命名。

这样方便程序猿进行调试

🎄Thread 的几个常见属性

在这里插入图片描述
常见属性说明:

  • ID 是线程的唯一标识,不同线程不会重复

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

  • 状态表示线程当前所处的一个情况,后面博主会一一介绍

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

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

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

  • 线程的中断问题,下面博主会进一步说明

程序举例,有以下程序(Thread.currentThread()表示返回当前线程对象的引用)

public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ": 我还活着");
                            Thread.sleep(1 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + ": 我即将死去");
        },"遇事问春风乄");
        System.out.println(Thread.currentThread().getName()
                + ": ID: " + thread.getId());
        System.out.println(Thread.currentThread().getName()
                + ": 名称: " + thread.getName());
        System.out.println(Thread.currentThread().getName()
                + ": 状态: " + thread.getState());
        System.out.println(Thread.currentThread().getName()
                + ": 优先级: " + thread.getPriority());
        System.out.println(Thread.currentThread().getName()
                + ": 后台线程: " + thread.isDaemon());
        System.out.println(Thread.currentThread().getName()
                + ": 活着: " + thread.isAlive());
        System.out.println(Thread.currentThread().getName()
                + ": 被中断: " + thread.isInterrupted());
        thread.start();
        while (thread.isAlive()) {}
        System.out.println(Thread.currentThread().getName()
                + ": 状态: " + thread.getState());
    }
}

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

🍀start()-启动一个线程

之前我们已经看到了如何通过覆写 run 方法创建一个线程对象,但线程对象被创建出来并不意味着线程就开始运行了。

  • 覆写 run 方法是提供给线程要做的事情的指令清单

  • 线程对象可以认为是张三把 李四、王五叫过来了

  • 而调用 start() 方法,就是张三喊一声:”行动起来!“,线程才真正独立去执行了
    在这里插入图片描述
    调用 start 方法, 才真的在操作系统的底层创建出一个线程

🌲中断一个线程

李四一旦进到工作状态,他就会按照行动指南上的步骤去进行工作,不完成是不会结束的。但有时我们需要增加一些机制,例如老板突然来电话了,说转账的对方是个骗子,需要赶紧停止转账,那张三该如何通知李四停止呢?这就涉及到我们的停止线程的方式了。

目前常见的有以下两种方式:

  1. 通过共享的标记来进行沟通

  2. 调用 interrupt() 方法来通知

🚩实例一

使用自定义的变量来作为标志位.

  • 需要给标志位上加 volatile 关键字(这个关键字的功能后面介绍,就暂时理解为一个共享的变量)

比如有以下程序:

public class ThreadDemo1 {
    private static class MyRunnable implements Runnable {
        public volatile boolean isQuit = false;
        @Override
        public void run() {
            while (!isQuit) {
                System.out.println(Thread.currentThread().getName()
                        + ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()
                    + ": 啊!险些误了大事");
            System.out.println("停止转账");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName()
                + ": 让李四开始转账。");
        thread.start();
        Thread.sleep(10 * 1000);
        System.out.println(Thread.currentThread().getName()
                + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
        target.isQuit = true;
    }
}

运行结果如下:
在这里插入图片描述
我们可以里看到当李四收到了受骗的通知后,停止了转账行为

🚩实例二

使用Thread.interrupted() 或者 Thread.currentThread().isInterrupted()代替自定义标志位.

Thread 内部包含了一个 boolean 类型的变量作为线程是否被中断的标记

在这里插入图片描述
比如以下程序:

public class ThreadDemo2 {
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            // 两种方法均可以
            while (!Thread.interrupted()) {
                //while (!Thread.currentThread().isInterrupted()) {
                System.out.println(Thread.currentThread().getName()
                        + ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println(Thread.currentThread().getName()
                            + ": 有内鬼,终止交易!");
                    // 注意此处的 break
                    break;
                }
            }
            System.out.println(Thread.currentThread().getName()
                    + ": 啊!险些误了大事");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName()
                + ": 让李四开始转账。");
        thread.start();
        Thread.sleep(10 * 1000);
        System.out.println(Thread.currentThread().getName()
                + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
        thread.interrupt();
    }
}

运行结果如下:
在这里插入图片描述
hread 收到通知的方式有两种:

  1. 如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以InterruptedException 异常的形式通知,清除中断标志当出现InterruptedException 的时候, 要不要结束线程取决于 catch 中代码的写法. 可以选择忽略这个异常, 也可以跳出循环结束线程.

上述代码中,博主在catch里加了break,所以停止了交易,当我们去掉break时,效果如下:
在这里插入图片描述
我们再来看一下运行结果:
在这里插入图片描述
我们发现我们如果不去结束循环,该线程会在抛出异常后继续运行。

这就将主动权交到了我们程序员自己的手上,你通知归通知,停不停止是我自己的决定的

  1. 否则,只是内部的一个中断标志被设置,thread 可以通过
  • Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志

  • Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志

这种方式通知收到的更及时,即使线程正在 sleep 也可以马上收到

🚩实例三

观察标志位是否清除

标志位是否清除, 就类似于一个开关.

  • Thread.interrupted() 相当于按下开关, 开关自动弹起来了. 这个称为 “清除标志位”
  • Thread.currentThread().isInterrupted() 相当于按下开关之后, 开关弹不起来, 这个称为 “不清除标志位”
  • 使用 Thread.interrupted() , 线程中断会清除标志位
    代码如下:
public class ThreadDemo3 {
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.interrupted());
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        thread.start();
        thread.interrupt();
    }
}

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

  • 使用 Thread.currentThread().isInterrupted() , 线程中断标记位不会清除.
    代码如下:
public class ThreadDemo4 {
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().isInterrupted());
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        thread.start();
        thread.interrupt();
    }
}

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

🎍join()-等待一个线程

有时,我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作。

例如,张三只有等李四转账成功,才决定是否存钱,这时我们需要一个方法明确等待线程的结束

代码示例如下:

public class ThreadDemo5 {
    public static void main(String[] args) throws InterruptedException {
        Runnable target = () -> {
            for (int i = 0; i < 3; i++) {
                try {
                    System.out.println(Thread.currentThread().getName()
                            + ": 我还在工作!");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + ": 我结束了!");
        };
        Thread thread1 = new Thread(target, "李四");
        Thread thread2 = new Thread(target, "王五");
        System.out.println("先让李四开始工作");
        thread1.start();
        thread1.join();
        System.out.println("李四工作结束了,让王五开始工作");
        thread2.start();
        thread2.join();
        System.out.println("王五工作结束了");
    }
}

运行结果为:
在这里插入图片描述
上述只是一个简单的应用,join()还提供了其他方法
在这里插入图片描述
关于 join 还有一些细节内容,博主会在后面的章节进行讲述

🚩获取当前线程引用

这个方法我们以及非常熟悉了,前面都已经使用过了,就不做过多赘述了

public static Thread currentThread();返回当前线程对象的引用

🚩休眠当前线程

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

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

关于 sleep,以后博主还会有一些知识会给大家补充的。

⭕总结

关于《【JavaEE初阶】 Thread类及常见方法》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

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

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

相关文章

如何选择UMLChina服务

服务口号&#xff1a;聚焦最后一公里 斐力庇第斯从马拉松跑回雅典报信&#xff0c;虽然已是满身血迹、精疲力尽&#xff0c;但他知道&#xff1a;没有出现在雅典人民面前&#xff0c;前面的路程都是白费。 学到的知识如果不能最终【用】于您自己的项目之中&#xff0c;也同样是…

设备搭建(waf、蜜罐、ids和ips)

文章目录 防火墙waf网闸蜜罐idsips 防火墙 DMZ区域叫非军事化区减&#xff0c;DMZ有web服务或者MySQL服务&#xff0c;从互联网到dmz的流量一般不拦截&#xff08;因为需要互联网用户访问web服务&#xff09;&#xff0c;如果dmz沦陷&#xff0c;攻击者想要继续横向移动到内网…

系统03:15min导图复习 文件管理

&#x1f433;前言 图源&#xff1a;文心一格 考研笔记整理&#xff0c;纯复习向&#xff0c;思维导图基本就是全部内容了&#xff0c;不会涉及较深的知识点~~&#x1f95d;&#x1f95d; 第1版&#xff1a;查资料、画思维导图~&#x1f9e9;&#x1f9e9; 编辑&#xff1a; …

layui laydate实现日期选择并禁用指定的时间

最终实现禁用2023-9-26这天的效果 官网地址 日期和时间组件文档 - layui.laydate 下面是实现的代码 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>layDate快速使用</title><link rel"stylesheet"…

IPSG技术和IP组播

1&#xff0c;IPSG技术概述 实验&#xff1a; DHCP snooping IPSG 拓扑&#xff1a; 需求&#xff1a; 1&#xff0c;实现PC1 和PC2 动态获取IP地址 2, 在SW2 配置DHCP snooping 实现DHCP 服务器的安全 3, 在 连接PC 1 和 PC2 的 接口上 做IPSG &#xff0c;防止终端…

AWD训练赛QWQ

使用D盾啥都没扫到&#xff0c;河马倒是扫了挺多东西&#xff0c;但是代码审计能力太差&#xff0c;不怎么看得懂 一般这里我们如果扫到那种很明显的一句话木马&#xff0c;直接删掉&#xff0c;爆出对手IP后尝试利用 代码审计能力不好&#xff0c;只能从网站页面入手 是一个登…

集合的基本运算

集合的运算等式&#xff1a; 常用的集合运算不等式&#xff1a; 、 试题 A&#xff0c;B&#xff0c;C是集合&#xff0c;证明&#xff1a;(A-B)-CA-(B∪C) 【答案】 设A、B、C是集合&#xff0c;证明 (A∪B)-C(A-C)∪(B-C)。 【答案】 已知A{1,2,3}&#xff0c;A-B{1,2}&…

【观察】天翼云政务大模型“慧泽”:推动政务服务再升级,加速智慧城市再进化...

进入2023年以来&#xff0c;AIGC的爆发式增长推动了全球步入一个全新时代——大模型时代&#xff0c;它不仅引发了AI产业的整体升级换代&#xff0c;同时大模型与行业和应用场景的深度融合&#xff0c;更加速了AI的“走深向实”。 其中&#xff0c;政务业务不仅是连接政府、企业…

FinClip PC 终端支持更新,现已兼容抖音与支付宝小程序

产品方面的相关动向 FinClip 全新升级&#xff01;现已兼容抖音小程序与支付宝小程序 自从 FinClip Studio 上线后&#xff0c;我们收到很多开发者对于“支持兼容抖音小程序与支付宝小程序”的需求反馈&#xff0c;现在 FinClip Studio 对抖音小程序和支付宝小程序的全面支持…

槽道流CFD结果与理论解对比

目录 理论CFD验证code 理论 理论参考文献 对于槽道流&#xff0c;理论上近壁面时均速度为线性分布&#xff0c;远离壁面处为对数分布 在对数区&#xff0c;有两个未知参数&#xff0c;两个人标定了不同的两组数据。 可以看出还是有一定区别的。 CFD验证 CFD有两组数据&…

2023年陕西省安全员B证证模拟考试题库及陕西省安全员B证理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年陕西省安全员B证证模拟考试题库及陕西省安全员B证理论考试试题是由安全生产模拟考试一点通提供&#xff0c;陕西省安全员B证证模拟考试题库是根据陕西省安全员B证最新版教材&#xff0c;陕西省安全员B证大纲整理…

一文掌握项目经理面试难题及其回答要点【干货收藏】

大家好&#xff0c;我是老原。 转眼就来到了10月&#xff0c;金九银十&#xff0c;想着你可能面试用得上&#xff0c;就又准备了一份2023最新版。 在看面试题之前&#xff0c;你要了解&#xff0c;面试题的本质到底是考察你什么&#xff0c;再根据这个大原则&#xff0c;收集面…

ai智能机器人要怎么运营更好

运营机器人核心关注的只有两个点&#xff0c;一个是机器人话术库的关键词是否充足&#xff0c;二是对录音的高要求。每一个话术&#xff0c;都把它当成一个重要的项目来做。比如做需求调研&#xff0c;学习客户的行业知识&#xff0c;了解他们这个行业打电话的语气语调。其它的…

爱普生L125X_L325X系列打印机Wi-Fi配置方法(Smart Panel)

准备工作&#xff1a; 手机需要下载“Epson Smart Panel”APP&#xff1b; 配置无线&#xff08;Wi-Fi&#xff09;方法 说明&#xff1a;SSID名称&#xff08;Wi-Fi名&#xff09;不能包含中文字符,路由器需要选择2.4GHz频段; 1. 打开“Epson Smart Panel”软件&#xff0…

vue3飞书扫码登录网页

二维码 SDK 接入文档 飞书官方文档链接 https://open.feishu.cn/document/common-capabilities/sso/web-application-sso/qr-sdk-documentation 最后更新于 2023-08-08 概述 为了实现网页接入飞书授权登录工作&#xff0c;将飞书登录的二维码嵌入到网页中。当用户扫码成功后…

斐波那契前 n 项和 - 矩阵乘法快速幂

1303. 斐波那契前 n 项和 - AcWing题库 构造矩阵A使 0 1 0 A [ 1 1 1 ] 0 0 1 然后对这个式子进行快速幂&#xff0c;挺神奇的 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);ci…

gcc 9版本 使用std::thread时候 的链接错误 undefined reference to `pthread_create‘

偶然发现 同样的代码 在 不同版本的ubuntu上编译的时候 一个能编译通过 一个不能 编译通过的版本 编译失败的版本 编译失败的提示 找不到pthread_create函数 成功的系统是ubuntu22.04 失败的是 ubuntu18.04 失败的加上lpthread 库之后可以编译过 ldd看下 可以发现…

保卫你的应用:探索过滤器和拦截器的奥秘

保卫你的应用&#xff1a;探索过滤器和拦截器的奥秘 前言概述实现原理不同使用范围不同触发时机不同注入Bean情况不同springboot中的实现 前言 在现代Web开发中&#xff0c;安全性和性能是至关重要的因素。过滤器和拦截器是Web应用中的两个关键概念&#xff0c;它们可以帮助你…

【软件测试】JUnit详解

文章目录 一. Junit是什么?二.Junit中常见的注解1. Test2. BeforeAll & AfterAll3. BeforeEach & AfterEach4. ParameterizedTest参数化5. Disabled6. Order 三. 测试套件1. 通过class运行测试用例2. 通过包运行测试用例 四. 断言 一. Junit是什么? JUnit是一个用于…

3D打印机升级killpper

本来是想整台新机的&#xff0c;但是想想老机器4max也不能就此放弃&#xff0c;看了看视频&#xff0c;改装升级似乎也没有那么难。然后就是换了喷头、皮带、轴承、挤出机、打印平台、加热板等等。做了干燥箱&#xff0c;改装挤出机结构来适配&#xff0c;风扇口也一并搞掉&…