[Java EE] 多线程(二): 线程的创建与常用方法(下)

2.3 启动一个线程–>start()

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

  • 覆写run方法是给线程提供了所要做的事情的指令清单
  • 创建线程对象就是把干活的人叫了过来.
  • 而调用start方法,就是喊一声"行动!!",线程会拿着事先准备好的指令清单去完成所要执行的事情.
  • 调用start方法,才是真正在操作系统中创建了PCB.
    下面我们用大家所感兴趣的领取任务类游戏来说明:
    原神,启动!!!
    在这里插入图片描述
  1. 首先,比如说我们要去任务列表那里领取任务,任务列表在你领取任务之前,就已经把你任务要做的事情规划好了,也就是该线程要做的任务,都规划在了run()方法中,这里的每一个任务就对应着一个线程,每一个任务中都有我们所要做的事情,也就是run()方法中所写的东西.
    在这里插入图片描述
  2. 比如说我们要做一个每日委托的任务,在你靠近任务区域之前会触发委托,我们已经准备就绪做任务了.此时便相当于创建了线程对象.
    在这里插入图片描述
  3. 我们在完成每日委托任务的时候,总是要进入战斗状态,打败怪物,来完成委托,当我们在怪物的身上打出了第一点伤害,我们就开始正式执行每日委托任务了,也就是线程通过start()方法正式启动.
    在这里插入图片描述

2.4 中断一个线程

⽬前常⻅的有以下两种⽅式:

  1. 通过共享的标记来进⾏沟通
  2. 调⽤interrupt()⽅法来通知

实例一:通过使用自定义变量来作为标识位

public class Demo1 {
    public static boolean isRunning = true;//把此变量先设置为true
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            while (isRunning){//isRunning为真,执行,为假,不执行
                System.out.println("hello tread");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();
        try {
            Thread.sleep(1500);//执行1.5s后修改标识位
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        isRunning = false;
    }
}

中断线程常用的方法如下:

方法说明
public void interrupt()中断对象关联的线程,如果线程正在阻塞,那么强制唤醒线程
public static boolean interrupted()判断当前线程是否中断
public boolean isinterrupted()判断对象关联的线程是否中断

补充:用Tread.currentTread()来获取当前线程的引用对象.所以判断当前线程是否中断就有了两个方法,第一个方法就是Tread.interrupted(),另一种就是Tread.currentTread().isinterrupted().

实例二:通过使用interrupt()方法来中断线程

public class Demo2 {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("hello tread");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        thread.interrupt();//中断线程
    }
}

这里使用interrupt()方法来中断一个线程与使用标志位的最大区别就是是否在线程休眠的时候强制唤醒线程.如果使用标志位的方法来终止线程,那么线程休眠的时候,就不会唤醒线程,线程依然处于休眠的状态,而使用interrupt()方法可以唤醒线程,使得线程触发sleep唤醒异常,最后在catch方法中来处理唤醒异常,也就是唤醒之后干什么,是可以由程序员自己决定的.

显然,我们在实际开发中,最多使用的是第二种方法,第一种方法不可唤醒线程,线程会继续阻塞,会使得线程的效率大大降低.

下面我们来展示几种线程被唤醒常见的异常处理方法:

  1. 直接终止线程
public class Demo2 {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("hello tread");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    break;//直接使用break终止线程
                }
            }
        });
        thread.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        thread.interrupt();
    }
}

  1. 抛出异常,并终止线程
public class Demo2 {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("hello tread");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);//抛出异常
                }
            }
        });
        thread.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        thread.interrupt();
    }
}

  1. 打印栈错误信息
public class Demo2 {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            while (Thread.currentThread().isInterrupted()){
                System.out.println("hello tread");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        thread.interrupt();
    }
}

但是这种方法我们会发现,打印栈错误信息后并不可以真正终止线程:
在这里插入图片描述
这是为什么呢?是因为我们在sleep被唤醒之后,会清除刚才的标志位,所以才会继续执行,所以线程是否终止,是由线程自己说了算,interrupt方法只是给出建议.

我们下面举例来区分它们几个:
下面有请我们的助教:灰太狼,红太狼登场.

  1. 红太狼让灰太狼出门抓羊,
  2. 灰太狼现在正在打游戏,灰太狼现在有两种选择,第一就是立刻停下手中的游戏去抓羊,就是使得线程立刻终止,直接break掉或者抛出异常
  3. 第二种选择就是先答应红太狼一声,等打完这把游戏之后,再去抓羊.就是打印栈错误信息之后并没有直接终止.
  4. 最后一中当然就是直接无视红太狼,继续打游戏,就是catch中什么都不写,把标志位改回来之后继续执行,下场就是…
    在这里插入图片描述
    平底锅伺候!!!

2.5 等待线程–>join()

有时,我们需要等待⼀个线程完成它的⼯作后,才能进行自己的下⼀步⼯作.所以我们便引入了join方法:重点一句话,谁调用join方法,谁就要进入阻塞状态去等待那个被调用join方法的线程结束

方法说明
public void join()等待线程结束(死等)
public void join(long millis)等待现场结束,最多等x毫秒
public void join(long millis,int nanos)比上一个方法更精确,可以精确到纳秒

我们下面拿一个具体的例子来说明:

public class Demo4 {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("tread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();
        try {
            thread.join();//在这里,main线程会进入阻塞状态,等待tread线程结束
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("main tread is terminate");
    }
}

运行结果:
在这里插入图片描述
在main线程中调用join方法,有以下两种可能:

  1. 若t线程已经结束,此时join就会立即返回.
  2. 若t线程此时还没有结束,join就会继续阻塞等待,一直到t线程结束.

下面我们举一个例子来说明上述问题:
有请助教:达达利亚,钟离登场
钟离邀请达达利亚去万名堂去吃饭,钟离此时是main线程,是他主动发起的邀请,情况一就是钟离先到的早,此时钟离并没有打电话叫达达利亚,就一直等(main,join之后,进入阻塞状态,死等达达利亚)达达利亚到了之后,再去一起吃饭.
情况二就是达达利亚到的早,之后达达利亚直接打电话叫了钟离,钟离直接停下手中的活(join直接返回)下楼去和达达利亚一起去吃饭.
情况三,钟离也是一个有底线的人,由于达达利亚迟迟不肯到来,所以钟离不可以等了(join(限制时间)),再等肚子都要饿扁了,直接离开了在这里插入图片描述

[注意]
在一般情况下,我们不使用死等的的方式去等待线程响应,我们一般是有时间的等.

2.6 休眠当前线程

也是我们比较熟悉⼀组方法,有⼀点要记得,因为线程的调度是不可控的,所以,这个方法只能保证实际休眠时间是⼤于等于参数设定休眠时间.因为线程从回复就绪状态到CPU上执行还需要一定的时间.

public class Demo10 {
    public static void main(String[] args) throws InterruptedException {
        System.out.println(System.currentTimeMillis());
        Thread.sleep(3 * 1000);
        System.out.println(System.currentTimeMillis());
    }
}

在这里插入图片描述
我们看到执行的结果相减并不是准确的3000ms,有一定的时间差异.

3. 线程的状态

3.1 线程的状态分类

线程的状态,可以通过==getState()==方法来获取到.
• NEW:Tread对象已经创建,但是还没有start
• RUNNABLE:处于就绪状态
• BLOCKED:后续介绍
• WAITING:死等进入阻塞
• TIMED_WAITING:带有超时时间的等进入阻塞
• TERMINATED:线程已经终止,但是Tread对象还在,未被gc回收.

public class Demo8 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
            for (int i = 0; i < 5; i++) {
                System.out.println("tread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        Thread thread1 = new Thread(()->{
            for (int i = 0; i < 5; i++) {
                System.out.println("tread1");
                if (i == 1){
                    try {
                        thread.join(3000);//等待时间3s
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        System.out.println(thread.getState());
        thread1.start();
        thread.start();
        System.out.println(thread.getState());
        Thread.sleep(2000);
        System.out.println(thread1.getState());
        thread.join();
        thread1.join();
        System.out.println(thread.getState());
        System.out.println(thread.getState());
    }
}

运行结果:
在这里插入图片描述
把注释处的时间去掉:
thread.join();
可见tread1的状态在等待tread的过程中变为了WAITING.
在这里插入图片描述

3.2 线程状态的转移

一条主线三条支线:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

国产主流数据库存储类型简析

国产数据库在技术架构上主要分为集中式、基于中间件分布式和原生分布式架构&#xff0c;衍生出集中式架构和分布式架构。那么在这些部署架构中&#xff0c;从数据分布的视角来看&#xff0c;在数据库中数据分布的形态是怎样的。本文将简要分析OceanBase、PolarDB、OpenGauss、G…

【Spring】-编程式事务和声明式事务

spring中控制事务的方式有两种&#xff1a;编程式事务和声明式事务&#xff0c;今天我以两种事务出发&#xff0c;对spring中实现事务的EnableTransactionManagement和Transaction两个注解的底层原理进行讨论。 一、编程式事务 什么是编程式事务&#xff1f; 硬编码的方式实现…

牛客NC197 跳跃游戏(一)【中等 动态规划 Java、Go、PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/23407eccb76447038d7c0f568370c1bd 思路 答案说的merge区间就是每个A[i]的地方能跳到的最远坐标是A[i] [i]&#xff0c; 有一个maxReach&#xff0c;遍历一遍A[i], 不断刷新MaxReach, 如果某个i 位置比maxReac…

MT3023 歌词中找单词

1.暴力 10/12 #include <bits/stdc.h> using namespace std; int n; string a[10005]; int main() {cin >> n;for (int i 0; i < n; i)cin >> a[i];string ll;cin >> ll;for (int i 0; i < n; i){string u a[i];int num 0;int j 0;for (in…

ssm056基于Java语言校园快递代取系统的设计与实现+jsp

校园快递代取系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园快递代取系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…

【在线OJ】雪花算法代码实现

雪花算法 用一个64比特位的long类型来作为生成id的类型&#xff0c;首先我们要了解哪些位置对应的意义&#xff0c;其中在本项目中10位的工作机器id被细分位5bit的机房id与5bit的机器id。雪花算法支持每毫秒生成2的12次方-1个id。 用一个64比特位的long类型来作为生成id的类型…

unity制作拼接地图

前段时间有个朋友问我想要制作一款地图编辑器&#xff0c;最开始我还想着在一个平面用节点切割制作地图编辑器这倒是也行&#xff0c;但不太好控制每一个点&#xff0c;如果未来项目大了&#xff0c;更加不好维护。 偶然间翻到一篇文章&#xff1a;unity地图边缘检测 或许我们…

upload-labs第七八关

第七关 $is_upload false; $msg null; if (isset($_POST[submit])) {if (file_exists(UPLOAD_PATH)) {$deny_ext array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml"…

SaaS智慧工地云平台源码 支持二次开发、支持源码交付

目录 智慧工地云平台功能模块 一、劳务管理系统 二、视频监控系统 三、危大工程管理 四、环境监测系统 五、材料管理系统 六、进度管理系统 通过人员管理、车辆管理、视频监控、施工质量、设备管理、环境监测、能耗监测七大维度提供面向工程管理人员的现场综合指挥管理平…

51单片机工程模板的建立(基于STC15系列库)

一、开启前准备 1.STC15官方库文件 1.1 stc15-software-lib-v1.0.rar&#xff1b;下载地址&#xff1a;STC15系列库&#xff08;带使用手册&#xff09;资源-CSDN文库 2.Keil4_C51软件&#xff0c;或其它版本&#xff1b; 二、创建工程模板 1.建立文件分类 listing&#xf…

PyTorch深度学习之旅:从入门到精通的十个关键步骤

在人工智能的浪潮中&#xff0c;深度学习框架扮演着至关重要的角色。PyTorch作为其中的佼佼者&#xff0c;以其简洁、直观和灵活的特性&#xff0c;吸引了众多开发者与研究者。本文将引导您逐步掌握PyTorch&#xff0c;从基础概念到高级应用&#xff0c;让您在深度学习的道路上…

斯坦福发布法律指令数据集LawInstruct,统一17个辖区24种语言

在法律领域&#xff0c;语言模型&#xff08;Language Models, LLMs&#xff09;的发展一直面临着独特的挑战。法律文本的复杂性、专业术语的广泛使用以及对精确性和可靠性的极高要求&#xff0c;使得法律领域的自然语言处理&#xff08;Natural Language Processing, NLP&…

工业数学模型——高炉煤气发生量预测(三)

1、工业场景 冶金过程中生产的各种煤气&#xff0c;例如高炉煤气、焦炉煤气、转炉煤气等。作为重要的副产品和二次能源&#xff0c;保证它们的梯级利用和减少放散是煤气能源平衡调控的一项紧迫任务&#xff0c;准确的预测煤气的发生量是实现煤气系统在线最优调控的前提。 2、…

JRT在线初始化完善

之前实现的在线初始化留了个尾巴&#xff0c;那就是环境下载页构造zip包的时候没修改JRTBrowser的连接串地址为当前网站&#xff0c;这样就要求网站部署好之后给用户下载之前有人要把服务器的浏览器地址配置好。这样就增加一个运维工作&#xff0c;如果忘了或者不知道的人就会导…

基于SSM的计算机课程实验管理系统的设计与实现(内附设计LW + PPT+ 源码下载)

基于SSM的计算机课程实验管理系统的设计与实现 项目名称&#xff1a; 基于SSM的计算机课程实验管理系统的设计与实现 项目技术栈 该项目采用了以下核心技术栈&#xff1a; 后端框架/库&#xff1a; SSM (Spring Spring MVC MyBatis)数据库&#xff1a; MySQL前端技术&…

01 JavaScript学习 导读

什么是JavaScript&#xff1f; JavaScript 是一种用于创建交互式网页和网络应用程序的脚本语言。它是一种高级、动态类型的语言&#xff0c;广泛用于客户端网页开发&#xff0c;可以用来增强网页的交互性并实现各种功能。 以下是 JavaScript 的一些重要特点和用途&#xff1a;…

Linux中进程和计划任务

一.程序 1.什么是程序 &#xff08;1&#xff09;是一组计算机能识别和执行的指令&#xff0c;运行于电子计算机上&#xff0c;满足人们某种需求的信息化工具 &#xff08;2&#xff09;用于描述进程要完成的功能&#xff0c;是控制进程执行的指令集 二.进程 1.什么是进程…

ORAN C平面 Section Extension 23

ORAN C平面Section扩展23用于任意symbol模式的调制压缩参数。此section扩展允许为一个或多个“SymPrbPatterns”指定多组“mcScaleReMask、csf和mcScaleOffset”值。“SymPrbPattern”用于指定一组PRB&#xff0c;这些PRB可以跨越使用prbPattern指定的整个PRB范围&#xff08;频…

20240329-1-SVM面试题

SVM面试题 1. SVM直观解释 SVM&#xff0c;Support Vector Machine&#xff0c;它是一种二分类模型&#xff0c;其基本模型定义为特征空间上的间隔最大的线性分类器&#xff0c;间隔最大使它有别于感知机&#xff1b;其还包括核技巧&#xff0c;这使它成为实质上的非线性分类…

ACID模型是什么

ACID模型是什么 ACID模型是数据库管理系统中保证事务处理安全性的一组特性。ACID是原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;和持久性&#xff08;Durability&#xff09;四个英文单词的…