【JavaEE多线程】Thread类及其常见方法(上)

news2024/12/23 5:35:09

系列文章目录

🌈座右铭🌈:人的一生这么长、你凭什么用短短的几年去衡量自己的一生!

💕个人主页:清灵白羽 漾情天殇_计算机底层原理,深度解析C++,自顶向下看Java-CSDN博客

❤️相关文章❤️:清灵白羽 漾情天殇-CSDN博客


目录

系列文章目录

前言

一、Thread构造方法

        1、Thread():

        2、Thread(Runnable target):

        拓展:

        1、Thread.sleep():

        2、sleep为什么要捕获异常:

        3、捕获异常之后呢?

        1、提供线程中断的机制

        2、保留中断状态

        3、提供了可靠的中断相应机制

        4、线程收到异常之后会做什么呢?

        1、恢复中断状态、        

        2、根据实际需求进行是当的清理工作

        补充

        3、Thread(Runnable target, String name)

二、其它方法


前言

        这篇文章我来为大家详细地介绍一下Thread类的常见的方法,以及线程的一些相关操作,当中包括如何中止线程、等待线程。


一、Thread构造方法

        在Java当中Thread类是用于创建和操作线程的主要类之一,Thread类的常见构造方法如下:

        1、Thread():

        这是Thread类的默认构造方法,他创建一个新的线程对象,但是如果我们不指定线程的执行任务,它将不会进行任何操作。

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread();
        thread.start();
    }
}

        2、Thread(Runnable target):

        这个构造方法接受一个实现了Runnable接口的对象作为参数,通过这样的方法我们可以在新线程当中执行实现了Runnable接口的对象的run()方法。

        Thread类是Java当中用于创建和管理线程的类,每个线程都是通过Thread类的实例表示的,Runnable接口是一个功能性接口,它只包含了一个抽象方法run(),当一个类实现了Runnable接口并且提供了run()方法的具体实现的时候,该类的实例就可以被传递给Thread类的构造方法,这个实现了Runnable接口的类通常包含了需要在新线程当中执行的代码。

        这个构造方法接受一个实现了Runnable接口的对象作为参数,当创建一个新的Thread实例的时候,可以通过这个构造方法指定该线程要执行的代码,而这段代码通常就是传递进来的RUnnable对象的run()方法。

        为什么要采用这样的方式呢,因为我们可以将不同的任务封装在实现了Runnable接口的类的实例当中,并且将这些任务交给Thread对象执行,从而实现多线程编程,这种方式比直接拓展Thread类更加灵活,因为一个类只能直接继承一个父类,但是可以实现多个接口,因此使用Runnable接口可以更好地支持代码的复用和组合。下面我为大家用代码来进行演示:

class MyTask implements Runnable{
    @Override
    public void run() {
        for (int i = 0;i < 5; i++){
            System.out.println("Thread running");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
public class Main {
    public static void main(String[] args) {
        MyTask myTask = new MyTask();
        Thread thread = new Thread(myTask);
        thread.start();
        for (int i = 0;i < 5;i++){
            System.out.println("主线程正在执行");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

        拓展:

        1、Thread.sleep():

        这个方法会让当前线程休眠指定的时间,所谓的当前线程是指调用这个sleep方法的线程,例如如果我们在main方法也就是主线程当中调用这个方法就是让主线程进入休眠,如果我们在自己定义的实现了Runnable接口的类当中调用了这个方法就是新的线程在休眠。

        2、sleep为什么要捕获异常:

        不仅仅是sleep()方法,Thread类当中几乎所有的方法都需要捕获异常,或者抛出异常来处理这个问题,包括我们后需要讲到的join(),wait()方法都需要这样做,那么这是为什么呢?这是因为在Java当中线程在休眠的时候是看可以被打断的,那么这个时候sleep就会发出'InterruptedException'异常来提醒线程已经被中断,因此在使用Thread.sleep()方法的时候需要处理这个异常,通常的做法是使用try-catch块进行环绕并进行相应的处理,比如恢复中断状态或者执行其它逻辑,在我为大家写的示例代码当中即使我们没有明确的中断线程的代码,但是为了保持良好的编码习惯,我们依然捕获了'InterruptedException'异常,这样做的好处是即使未来我们对线程进行了中断操作,代码也已经准备好了处理这种情况,提高了代码的健壮性和可维护性,有很多小伙伴在初学的时候不明白为什么这里一定要进行异常处理,希望我的观点可以帮助到大家。

        3、捕获异常之后呢?

        Thread这个类在设计的时候让Thread.sleep()抛出'InterruptedException'异常的主要目的是为了提供一种机制来响应线程的中断请求,Java中的线程中断机制允许一个线程中断另外一个线程的执行,当一个线程调用另一个线程的'interrupted'方法的时候,目标线程也就是被中断的线程就会收到一个中断请求,如果这个时候目标线程正在进行sleep(),wait(),join()方法当中休眠那么这个时候中断机制会将这个线程强制唤醒,并且唤醒之后收到一个'InterruptedException'异常信息。

        1、提供线程中断的机制

        通过抛出异常,允许线程在休眠期间被中断,使得线程可以在收到中断请求以后做出相应的处理,例如终止执行,清理资源等。

        2、保留中断状态

        当'InterruptedException'异常被捕获之后通常的做法是在catch块当中处理异常并且恢复线程中的中断状态,以便其它部分的代码可以检查到线程被中断,并且采取相应的行动。

        3、提供了可靠的中断相应机制

        通过抛出异常,确保了即使线程处于休眠状态,也能够及时响应中断请求(因为它会被立刻唤醒,这一点上面我们已经讲过了,这里就不再重复了),而不会无限地等待,这样可以使得多线程程序更加可靠和健壮。

        4、线程收到异常之后会做什么呢?

        1、恢复中断状态、        

        在catch块中使用‘Thread.currentThread().interrupt()’(这行代码我刚才的实例里面没有讲到,后面会为大家讲到。所以这里大家只做了解)来重新设置中断状态,以便其它部分的代码能够检查到线程是否被中断。

        2、根据实际需求进行是当的清理工作

        例如释放资源管理连接等,然后再根据业务的逻辑决定这个线程是否要继续执行,或者直接终止线程的执行不再被调用。

        补充

        我相信有很多小伙伴不太明白关于我上面讲到的关于恢复线程中断状态的概念,我在这里特别补充一下,线程中断状态是一个标志位,是线程TCB(线程控制块)内部自己维护的一个标志位用于表示线程是否被中断,当目标线程被中断的时候,中断状态就会被设置为true(初始状态为false),当线程在阻塞状态下(比如调用sleep、join等方法的时候)被中断的时候,会抛出'InterruptedException'异常,并且在抛出异常之前Java会清楚线程的中断状态,将中断状态重新设置为false,

        因此在处理这个异常的时候,通常需要更新设置线程的中断状态,以便将中断信息传递给更高层的调用栈,catch块当中的Thread.currentThread().interrupt()’会将线程的中断状态设置为之前的值,如果之前是true那么就设置为true如果之前是false亦然,在抛出异常之前清楚中断状态时为了让线程在异常处理之后继续执行,不会误认为被中断过,如果不清理中断状态,即使线程处理了’InterruptedException‘这个异常,但是在异常处理之后线程的中断状态仍然为true,我们要知道线程被中断一定会伴随着一系列的中断处理操作(这个我之前的文章里面有详细讲过这里就不一一介绍了)这样子的话会进行不必要的处理操作,所以在异常抛出之前就会清除中断状态保证异常是真正被中断的时候抛出,这是为了线程在异常处理之后能够正确地继续执行。

        我这里还要强调一点不要把清除中断状态和恢复中断状态搞混,清除中断状态是在抛出异常之前系统自动进行的,恢复中断状态是需要在catch块当中手动进行的,恢复中断状态是为了中断信息得以继续传递,通过清除线程的中断状态并且在适当的时候恢复它,使得线程可以在异常处理后继续执行,并且其他部分的代码可以根据需要处理中断请求。(这部分内容作为了解即可)

        3、Thread(Runnable target, String name)

        这里其实就是给线程起一个名字,内容很简单直接为大家用代码演示。

public class Main {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0;i < 5;i++){
                    System.out.println(Thread.currentThread().getName()
                    + "running task");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };

        Thread thread = new Thread(runnable,"Thread-1");
        Thread thread1 = new Thread(runnable,"Thread-2");
        thread1.start();
        thread.start();
    }
}

        Thread主要的几个构造方法就为大家介绍到这里,


二、其它方法

        后续的方法下一篇文章接着为大家介绍,希望这篇文章能够让你有所收获,我们明天再见!

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

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

相关文章

【opencv】dnn示例-segmentation.cpp 通过深度学习模型对图像进行实时语义分割

模型下载地址&#xff1a; http://dl.caffe.berkeleyvision.org/ 配置文件下载&#xff1a; https://github.com/opencv/opencv_extra/tree/4.x/testdata/dnn 该段代码是一个利用深度学习进行语义分割的OpenCV应用实例。下面将详细解释代码的功能和方法。 引入库 引入了一些必要…

蓝桥杯2024年第十五届省赛真题-宝石组合

思路&#xff1a;参考博客&#xff0c;对Ha,Hb,Hc分别进行质因数分解会发现&#xff0c;S其实就等于Ha&#xff0c;Hb&#xff0c;Hc的最大公约数&#xff0c;不严谨推导过程如下&#xff08;字丑勿喷&#xff09;&#xff1a; 找到此规律后&#xff0c;也不能枚举Ha&#xff…

Go 单元测试之mock接口测试

文章目录 一、gomock 工具介绍二、安装三、使用3.1 指定三个参数3.2 使用命令为接口生成 mock 实现3.3 使用make 命令封装处理mock 四、接口单元测试步骤三、小黄书Service层单元测试四、flags五、打桩&#xff08;stub&#xff09;参数 六、总结6.1 测试用例定义6.2 设计测试用…

医学图像三维重建与可视化系统 医学图像分割 区域增长

医学图像的三维重建与可视化&#xff0c;这是一个非常有趣且具有挑战性的课题&#xff01;在这样的项目中&#xff0c;可以探索不同的医学图像技术&#xff0c;比如MRI、CT扫描等&#xff0c;然后利用这些图像数据进行三维重建&#xff0c;并将其可视化以供医生或研究人员使用。…

解决Mac使用Vscode无法调用外部终端

前言 今天遇到一个很奇怪的问题&#xff0c;之前好好的用Vscode还能调用外部终端&#xff0c;怎么今天不行了&#xff1f;问题出在哪里呢&#xff1f;请听我娓娓道来。 检查配置文件 我查看了一下配置文件&#xff0c;发现配置文件都是调用外部控制台&#xff0c;没毛病啊。 …

Objective-C网络数据捕获:使用MWFeedParser库下载Stack Overflow示例

概述 Objective-C开发中&#xff0c;网络数据捕获是一项常见而关键的任务&#xff0c;特别是在处理像RSS源这样的实时网络数据流时。MWFeedParser库作为一个优秀的解析工具&#xff0c;提供了简洁而强大的解决方案。本文将深入介绍如何利用MWFeedParser库&#xff0c;以高效、…

(最详细)关于List和Set的区别与应用

关于List与Set的区别 List和Set都继承自Collection接口&#xff1b; List接口的实现类有三个&#xff1a;LinkedList、ArrayList、Vector。Set接口的实现类有两个&#xff1a;HashSet(底层由HashMap实现)、LinkedHashSet。 在List中&#xff0c;List.add()是基于数组的形式来添…

Spring Boot后端+Vue前端:打造高效二手车交易系统

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

机器学习笔记 - 使用 OpenCV 的结构化森林进行边缘检测

一、简述 边缘检测是计算机视觉领域中一项非常重要的任务。这是许多纯计算机视觉任务(例如轮廓检测)的第一步。即使涉及深度学习,较深层也首先学习识别边缘,然后再学习图像的复杂特征。所以,我们可以说边缘检测在计算机视觉领域非常重要。拥有良好且高效的图像边缘检测算法…

后端返回的数据中含有Null的则不在前端展示

方式 1&#xff1a;application 上加配置 只需要在配置文件 上&#xff0c;增加 如下配置。 application 格式配置&#xff1a; spring.jackson.default-property-inclusionnon_null yml 格式配置&#xff1a; spring:jackson:default-property-inclusion: non_null注意&a…

美团财务科技后端一面:如何保证数据一致性?延时双删第二次失败如何解决?

更多大厂面试内容可见 -> http://11come.cn 美团财务科技后端一面&#xff1a;项目内容拷打 美团财务科技后端一面&#xff1a;项目相关面试题&#xff0c;主要包含 Zset、延时双删失败重试、热点数据解决、ThreadLocal 这几个方面相关的内容 由于前几个问题是对个人项目的…

混合云构建-如何创建一个高可用的Site to Site VPN 连接 Azure 和GCP云

在现代云计算环境中,企业通常会采用多云战略,将工作负载分布在不同的云服务提供商上。这种方式可以提高可用性、降低供应商锁定风险,并利用每个云提供商的独特优势。然而,在这种情况下,需要确保不同云环境之间的互联互通,以实现无缝的数据传输和应用程序集成。 本文将详细介绍…

微信小程序之点击事件

微信小程序中常用的点击事件主要是 tap&#xff0c;但除此之外还有其他的触摸类事件&#xff0c;用于不同的交互场景。以下是一些常见的点击和触摸相关的事件及其区别&#xff1a; 1、tap——最基本的点击事件&#xff0c;适用于一般的轻触交互&#xff0c;类似于 HTML 中的 c…

浅析binance新币OMNI的前世今生

大盘跌跌不休&#xff0c;近期唯一的指望就是binance即将上线的OMNI 。虽然目前查到的空投数量不及预期&#xff0c;但OMNI能首发币安&#xff0c;确实远超预期了。 OMNI代币总量1亿&#xff0c;初始流通仅10,391,492枚&#xff0c;其中币安Lanchpool可挖350万枚 对于OMNI这个…

【做算法学数据结构】【链表】删除排序链表中的重复元素

链表 链表单向链表双向链表 题目代码 链表 当涉及到数据结构时&#xff0c;链表是一种常见且重要的数据结构。链表由一系列节点组成&#xff0c;每个节点包含数据和指向下一个节点的引用。相比于数组&#xff0c;链表的大小可以动态地增长或缩小&#xff0c;因为每个节点只需要…

风力发电自动化控制系统中的智能化技术应用研究

风力发电自动化控制系统中的智能化技术应用研究 随碳中和目标的提出和执行&#xff0c;风能发电作为新能源行业的核心部分&#xff0c;步入了它的黄金发展期。由于风能资源具有间歇性、随机性等特点&#xff0c;这给风电的高效利用带来了巨大挑战。为了增强风力发电系统的工作效…

枚举类型介绍

1.如果一个变量只有几种可能的值&#xff0c;比如星期几 son,mon,tus,wed,fri,sat 列表中的名字&#xff0c;可以自己定义&#xff0c;无需像变量一样去申请 枚举变量&#xff1a;只限列表中的情况&#xff0c;值默认从0开始&#xff0c;枚举元素不能被赋值&#xff0c;可以指定…

OpenCV从入门到精通实战(七)——探索图像处理:自定义滤波与OpenCV卷积核

本文主要介绍如何使用Python和OpenCV库通过卷积操作来应用不同的图像滤波效果。主要分为几个步骤&#xff1a;图像的读取与处理、自定义卷积函数的实现、不同卷积核的应用&#xff0c;以及结果的展示。 卷积 在图像处理中&#xff0c;卷积是一种重要的操作&#xff0c;它通过…

JAVA网络编程、项目验证码实现

什么是网络编程? 在网络通信协议下&#xff0c;不同计算机上运行的程序&#xff0c;进行的数据传输。 应用场景&#xff1a;即时通信、网游对战、金融证券、国际贸易、邮件、等等 不管是什么场景&#xff0c;都是计算机跟计算机之间通过网络进行数据传输 Java中可以使用ja…

面试经典算法系列之二叉树17 -- 验证二叉树

面试经典算法32 - 验证二叉树 LeetCode.98 公众号&#xff1a;阿Q技术站 问题描述 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当…