学习JavaEE的日子 Day29 yield,join,线程的中断,守护线程,线程局部变量共享,线程生命周期

Day29

多线程

12. 线程的礼让

Thread.yield();

理解:此方法为静态方法,此方法写在哪个线程中,哪个线程就礼让

注意:所谓的礼让是指当前线程退出CPU资源,并转到就绪状态,接着再抢

需求:创建两个线程A,B,分别各打印1-100的数字,其中B一个线程,每打印一次,就礼让一次,观察实验结果

public class Test01 {public static void main(String[] args) {A a = new A();B b = new B();a.start();b.start();}
}
public class A extends Thread{@Overridepublic void run() {for (int i = 1; i <= 100; i++) {System.out.println("A:" + i);}}
}
public class B extends Thread{@Overridepublic void run() {for (int i = 1; i <= 100; i++) {System.out.println("B:" + i);//礼让:让当前线程退出CPU资源,当前线程退出后立刻转入抢资源的状态,可能又会抢到CPU资源Thread.yield();}}
}

13. 线程的合并

t.join(); 合并方法

需求:主线程和子线程各打印200次,从1开始每次增加1,当主线程打印到10之后,让子线程先打印完再打印主线程

public class Test01 {public static void main(String[] args) throws InterruptedException {MyThread t = new MyThread();t.start();for (int i = 1; i <=200; i++) {System.out.println("主线程:" + i);if(i == 10){//让t线程加入到当前线程t.join();}}}
}
public class MyThread extends Thread{@Overridepublic void run() {for (int i = 1; i <=200; i++) {System.out.println("子线程:" + i);}}
}

14.线程的中断

14.1 线程的中断1

面试题:下列代码的子线程开启后,是否会在3000毫秒就被销毁?
答:不一定,因为3000毫秒后主线程才休眠结束,这时会抢CPU资源
如果立刻抢到,那么子线程就是3000毫秒后销毁
如果没有抢到CPU资源,那么子线程会继续运行,直到主线程抢到CPU资源

public class Test01 {public static void main(String[] args) throws InterruptedException {MyThread t = new MyThread();//子线程t.start();//主线程休眠3秒(Main方法就是主线程)Thread.sleep(3000);//过时了t.stop();//立刻停止(缺点:可能会导致功能缺失)	}}
public class MyThread extends Thread{@Overridepublic void run() {while(true){ //死循环System.out.println("111");System.out.println("222");System.out.println("333");System.out.println("444");}}
}
14.2 线程的中断2

另外一种写法:

该方法一定会执行到444结束,不像上面一种立马停止,可能在222或者333结束

public class Test01 {public static void main(String[] args) throws InterruptedException {MyThread t = new MyThread();t.start();Thread.sleep(3000);t.setFlag(false);}}
public class MyThread extends Thread{private boolean flag = true;public void setFlag(boolean flag) {this.flag = flag;}@Overridepublic void run() {while(flag){System.out.println("111");System.out.println("222");System.out.println("333");System.out.println("444");}}
}

14.3 线程的中断3

public class Test01 {public static void main(String[] args) throws InterruptedException {MyThread t = new MyThread();t.start();Thread.sleep(3000);//改变线程状态t.interrupt();}}
public class MyThread extends Thread{@Overridepublic void run() {//获取线程状态(是否消亡)
//		System.out.println(Thread.currentThread().isInterrupted());while(!Thread.currentThread().isInterrupted()){System.out.println("111");System.out.println("222");System.out.println("333");System.out.println("444");}}
}

15.守护线程/后台线程

守护线程 默默守护着前台线程,当所有的前台线程都消亡后,守护线程会自动消亡

注意:垃圾回收器就是守护线程

t.setDaemon(true);

public class Test01 {public static void main(String[] args) throws InterruptedException {MyThread t = new MyThread();t.setDaemon(true);//将当前线程设置为守护线程t.start();for (int i = 1; i <= 5; i++) {System.out.println("主线程:" + i);Thread.sleep(1000);}}
}
public class MyThread extends Thread{@Overridepublic void run() {while(true){System.out.println("后台线程默默守护着前台线程");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

十六、线程局部变量(实现线程范围内的共享变量)-- ThreadLocal

16.1 共享单个数据
public class Test01 {public static final ConcurrentHashMap<Thread, Integer> map = new ConcurrentHashMap<>();public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {int i = 10;//存数据map.put(Thread.currentThread(), i);A a = new A();B b = new B();a.println();//10b.println();//10}},"线程1").start();new Thread(new Runnable() {@Overridepublic void run() {int i = 20;//存数据map.put(Thread.currentThread(), i);A a = new A();B b = new B();a.println();//20b.println();//20}}, "线程2").start();}
}
public class A {public void println(){Thread t = Thread.currentThread();Integer value = Test01.map.get(t);System.out.println(t.getName() + "里的A类对象获取了数据:" + value);}
}
public class B {public void println(){Thread t = Thread.currentThread();Integer value = Test01.map.get(t);System.out.println(t.getName() + "里的B类对象获取了数据:" + value);}
}
16.2 共享多个数据-- ThreadLocal

存数据
local.set(data)底层原理:
1.获取当前线程对象
2.通过当前线程对象获取ThreadLocalMap<ThreadLocal,T>
3.map.put(this,t) * 获取数据

local.get()底层原理:
1.获取当前线程对象
2.通过当前线程对象获取ThreadLocalMap<ThreadLocal,T>
3.map.getEntry(this) -> Entry对象
4.entry.getValue()

public class Test01 {public static final ThreadLocal<Data> local = new ThreadLocal<>();public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {Data data = Data.getInstance(10,"xxx");/*** 存数据* local.set(data)底层原理:* 		1.获取当前线程对象* 		2.通过当前线程对象获取ThreadLocalMap<ThreadLocal,T>* 		3.map.put(this,t)*/local.set(data);A a = new A();B b = new B();a.println();//10b.println();//10}},"线程1").start();new Thread(new Runnable() {@Overridepublic void run() {Data data = Data.getInstance(20,"yyy");data = Data.getInstance(30,"zzz");//存数据local.set(data);A a = new A();B b = new B();a.println();//20b.println();//20}}, "线程2").start();}
}

数据包类

//数据包类
public class Data {private int i;private String str;//有参构造,无参构造,get,set方法省略//保证每个线程里只有一个Data包对象public static Data getInstance(int i,String str){Data data = Test01.local.get();//获取当前线程的Data对象if(data == null){data = new Data(i, str);Test01.local.set(data);}else{data.setI(i);data.setStr(str);}return data;}@Overridepublic String toString() {return "Data [i=" + i + ", str=" + str + "]";}
}
public class A {public void println(){Thread t = Thread.currentThread();/*** 获取数据* local.get()底层原理:* 		1.获取当前线程对象* 		2.通过当前线程对象获取ThreadLocalMap<ThreadLocal,T>* 		3.map.getEntry(this) -> Entry对象* 		4.entry.getValue()*/Data value = Test01.local.get();System.out.println(t.getName() + "里的A类对象获取了数据:" + value);}
}
public class B {public void println(){Thread t = Thread.currentThread();Data value = Test01.local.get();System.out.println(t.getName() + "里的B类对象获取了数据:" + value);}
}

17.线程的生命周期

1、新建状态

i. 在程序中用构造方法创建了一个线程对象后,新的线程对象便处于新建状态,此时,它已经有了相应的内存空间和其它资源,但还处于不可运行状态。新建一个线程对象可采用线程构造方法来实现。

ii. 例如:Thread thread=new Thread();

2、 就绪状态

i. 新建线程对象后,调用该线程的start()方法就可以启动线程。当线程启动时,线程进入就绪状态。此时,线程将进入线程队列排队,等待CPU调用,这表明它已经具备了运行条件。

3、运行状态

i. 当就绪状态的线程被调用并获得处理器资源时,线程就进入了运行状态。此时,自动调用该线程对象的run()方法。run()方法定义了该线程的操作和功能。

4、 阻塞状态

i. 一个正在执行的线程在某些特殊情况下,如被人为挂起,将让出CPU并暂时中止自己的执行,进入阻塞状态。在可执行状态下,如果调用sleep(2000)、wait()等方法,线程都将进入阻塞状态。阻塞时,线程不能进入排队队列,只有当引起阻塞的原因被消除后,线程才可以转入就绪状态。

5、死亡状态

i. 线程调用stop()方法时或run()方法执行结束后,线程即处于死亡状态。处于死亡状态的线程不具有继续运行的能力。

在这里插入图片描述

总结

1.线程的礼让 – yield

2.线程的合并 – join

3.线程的中断

4.守护线程

5.线程局部变量共享 – 重要

用,这表明它已经具备了运行条件。

3、运行状态

i. 当就绪状态的线程被调用并获得处理器资源时,线程就进入了运行状态。此时,自动调用该线程对象的run()方法。run()方法定义了该线程的操作和功能。

4、 阻塞状态

i. 一个正在执行的线程在某些特殊情况下,如被人为挂起,将让出CPU并暂时中止自己的执行,进入阻塞状态。在可执行状态下,如果调用sleep(2000)、wait()等方法,线程都将进入阻塞状态。阻塞时,线程不能进入排队队列,只有当引起阻塞的原因被消除后,线程才可以转入就绪状态。

5、死亡状态

i. 线程调用stop()方法时或run()方法执行结束后,线程即处于死亡状态。处于死亡状态的线程不具有继续运行的能力。

在这里插入图片描述

简答题

1.Thread类中的yield方法有什么作用?

Yield方法可以暂停当前正在执行的线程对象,让其它有相同优先级的线程执行。它是一个静态方法而且

只保证当前线程放弃CPU占用而不能保证使其它线程一定能占用CPU,执行yield()的线程有可能在进入

到暂停状态后马上又被执行。

2.sleep()和wait() 有什么区别?

对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。

sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。

当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用 notify()方法后本线程才进入对象锁定池准备,获取对象锁进入运行状态。

3.有三个线程T1,T2,T3,如何保证顺序执行?

在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用 T2,T2调用T1),这样T1就会先完成而T3最后完成。 实际上先启动三个线程中哪一个都行,因为在每个线程的run方法中用join方法限定了三个线程的执行顺序。

public class JoinTest2 {// 1.现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行public static void main(String[] args) {final Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("t1");}});final Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {try {// 引用t1线程,等待t1线程执行完t1.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t2");}});Thread t3 = new Thread(new Runnable() {@Overridepublic void run() {try {// 引用t2线程,等待t2线程执行完t2.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t3");}});t3.start();//这里三个线程的启动顺序可以任意,大家可以试下!t2.start();t1.start();}
}

简答题

如何停止一个正在运行的线程

1、使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。

2、使用stop方法强行终止,但是不推荐这个方法,因为stop和suspend一样都是过期作废的方法。

3、使用interrupt方法中断线程。

class MyThread extends Thread {
volatile boolean stop = false;
public void run() {
while (!stop) {
System.out.println(getName() + " is running");
try {
sleep(1000);
} catch (InterruptedException e) {
System.out.println("week up from blcok...");
stop = true; // 在异常处理代码中修改共享变量的状态
}
}
System.out.println(getName() + " is exiting...");
}
}
class InterruptThreadDemo3 {
public static void main(String[] args) throws InterruptedException {
MyThread m1 = new MyThread();
System.out.println("Starting thread...");
m1.start();
Thread.sleep(3000);
System.out.println("Interrupt thread...: " + m1.getName());
m1.stop = true; // 设置共享变量为true
m1.interrupt(); // 阻塞时退出阻塞状态
Thread.sleep(3000); // 主线程休眠3秒以便观察线程m1的中断情况
System.out.println("Stopping application...");
}
}

总结

1.线程的礼让 – yield

2.线程的合并 – join

3.线程的中断

4.守护线程

5.线程局部变量共享 – 重要

6.线程生命周期 — 重要

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

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

相关文章

Kimi和ChatGPT做古诗词阅读理解,谁更胜一筹?

前几天发过一篇Kimi整理会议的体验教程&#xff0c;没想到大家很感兴趣&#xff0c;这次再来拿Kimi做古诗词阅读理解看看&#xff0c;同时也对比下ChatGPT的效果。 ChatGPT是几乎家喻户晓的AI大模型&#xff0c;Kimi和它对比有哪些异同点呢&#xff1f; 首先它们都是基于对话…

【Flink架构】关于FLink BLOB的组织架构:FLIP-19: Improved BLOB storage architecture:官网解读

文章目录 一. BlobServer架构1.BlobClient2. BlobServer3. BlobCache4. LibraryCacheManager 二、BLOB的生命周期1. 分阶段清理2. BlobCache的生命周期3. BlobServer 三、文件上下载流程1. BlobCache 下载2. BlobServer 上传3. BlobServer 下载 四. Flink中支持的BLOB文件类型1…

uniapp流浪动物救助小程序Java宠物领养小程序springboot

uniapp流浪动物救助小程序Java宠物领养小程序springboot 代码40块&#xff0c;需要的私聊 前台基于uniapp小程序 后台管理基于springbootvue前后端分离项目 开发语言&#xff1a;Java 框架&#xff1a;springboot vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xf…

VTK 示例 基本的流程-事件交互、球体、

流程可以总结如下&#xff1a; 导入所需的头文件&#xff1a; 首先&#xff0c;导入了一系列 VTK 头文件&#xff0c;这些文件包含了所需的类和函数声明。 创建对象&#xff1a; 创建了两个球体&#xff08;一个较大&#xff0c;一个较小&#xff09;&#xff0c;一个平面&…

FANUC机器人KAREL语言程序结构(入门)

一、karel语言程序结构 FANUC机器人keral语言编程结构如下图所示&#xff1a; Keral指令对应的基础用法如下所示&#xff1a; 二、创建一个简单的写屏程序 依照对应的karel语法写写入下列程序 运行对应的程序进行测试&#xff1a;

南网科研院携手百度智能云,入选信通院AI原生应用优秀案例

为呈现AI原生研发和应用成效&#xff0c;提供AI原生相关技术、服务、部署、运营、基础设施等选型参考&#xff0c;近期&#xff0c;中国信息通信研究院发布了AI原生技术及应用优秀案例&#xff0c;由南方电网公司输配电部牵头、南方电网科学研究院有限责任公司&#xff08;以下…

Web安全攻防世界01 fileinclude(宜兴网信办)

<html> <head><meta http-equiv"Content-Type" content"text/html; charsetutf-8" /></head> //规定 HTML 文档的字符集<br /> <b>Notice</b>: Undefined index: language in <b>/var/www/html/index.ph…

Docket常见的软件部署1

1 安装MySQL # 查看MySQL镜像 docker search mysql # 拉起镜像 docker pull mysql:5.7 # 创建MySQL数据映射卷&#xff0c;防止数据不丢失 mkdir -p /hmoe/tem/docker/mysql/data/ # 启动镜像 docker run -d --name mysql -e MYSQL_ROOT_PASSWORD123456 -p 3306:3306 -v /home…

牛客NC79 丑数【中等 堆、优先级队列 Java,Go,PHP Go和PHP中我自己实现了优先级队列】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/6aa9e04fc3794f68acf8778237ba065b 思路 注意&#xff1a; 数据范围&#xff1a;0≤n≤2000&#xff0c; 2000肯定到不了&#xff0c;最多到1690&#xff0c;相同题目链接&#xff1a;https://www.lintcode.com…

Dockerfile:自定义镜像

Dockerfile 是一个文本文件&#xff0c;其中包含了一系列用于自动化构建Docker镜像的指令。通过编写Dockerfile&#xff0c;开发者能够明确地定义一个软件应用及其运行环境应该如何被封装进一个可移植、可重复构建的Docker镜像中。 第一步&#xff1a;在/tmp文件下新建docker…

hadoop 查询hdfs资源信息的方式

hdfs dfsadmin -report &#xff3b;-live&#xff3d;&#xff3b;-dead&#xff3d;&#xff3b;-decommissioning&#xff3d;

前缀和算法(1)

目录 一维前缀和[模板] 一、题目描述 二、思路解析 三、代码 二维前缀和[模板] 一、题目描述 二、思路解析 三、代码 724.寻找数组的中心下标 一、题目描述 二、思路解析 三、代码 238.除自身以外数组的乘积 一、题目描述 二、思路解析 三、代码 一维前缀和[模…

SQLynx发布3.0.0版本:带来更流畅便捷的SQL开发体验

作为新一代的一站式数据库管理开发工具&#xff0c; SQLynx自发布上线以来&#xff0c;一直受到广大用户的好评与鼓励。 为了给用户提供更高效、更便捷、更可靠的数据库管理开发体验&#xff0c;SQLynx今日正式发布3.0.0版本&#xff0c;同步在麦聪软件官网上线&#xff0c;全…

0DAY漏洞是什么,如何进行有效的防护

零日漏洞&#xff0c;指的是软件或系统中未被公开的、未被厂商知晓的安全漏洞。这些漏洞未被修复&#xff0c;因此黑客可以利用它们进行攻击&#xff0c;而受害者往往无法防范。由于这些漏洞的存在时间很短&#xff0c;因此称之为“零日漏洞”&#xff0c;也称为“0day漏洞”。…

VMware ESXi部署macOS Monterey

正文共&#xff1a;1024 字 30 图&#xff0c;预估阅读时间&#xff1a;2 分钟 最早使用黑苹果是在2015年&#xff0c;装在了古老的Acer商务本上&#xff08;老樹發新芽&#xff0c;acer tm 4750g裝黑蘋果&#xff09;&#xff1b;上次安装黑苹果是在两年前&#xff08;VMware…

淘宝详情数据采集(商品上货,数据分析,属性详情,价格监控),海量数据值得get

淘宝详情数据采集涉及多个环节&#xff0c;包括商品上货、数据分析、属性详情以及价格监控等。在采集这些数据时&#xff0c;尤其是面对海量数据时&#xff0c;需要采取有效的方法和技术来确保数据的准确性和完整性。以下是一些关于淘宝详情数据采集的建议&#xff1a; 请求示…

学习可视化比较好用的网站Apache ECharts

Apache ECharts 是一个基于 JavaScript 的开源可视化图表库&#xff0c;它提供了直观、交互丰富且可高度个性化定制的数据可视化图表。这个库最初由百度团队开源&#xff0c;并在 2018 年初捐赠给了 Apache 基金会&#xff0c;成为 ASF 的孵化级项目。在 2021 年 1 月 26 日&am…

LabVIEW2024中文版软件安装包、工具包、安装教程下载

下载链接&#xff1a;LabVIEW及工具包大全-三易电子工作室http://blog.eeecontrol.com/labview6666 《LabVIEW2024安装图文教程》 1、解压后&#xff0c;双击install.exe安装 2、选中“我接受上述许可协议”&#xff0c;点击下一步 3、点击下一步&#xff0c;安装NI Package …

ChatGPT赋能大气科学:GPT与Python结合应用遥感降水数据处理、ERA5大气再分析数据的统计分析、干旱监测及风能和太阳能资源评估等

目录 专题一 AI领域常见工具讲解 专题二 POE平台及ChatGPT使用方法 专题三 提示词工程 专题四 科研常见应用场景 专题五 Python简明教程 专题六 GPT科研绘图 专题七 GPT辅助下载数据 专题八 遥感降水数据 专题九 数据产品评估 专题十 ERA5全球大气再分析数据 专题十…

Xilinx IDDR及ODDR使用和仿真

平台&#xff1a;Vivado2018 官方相关文档&#xff0c;ug471_7Series_SelectIO.pdf 关于IDDR与ODDR Input DDR Resource(IDDR) 外部的数据在时钟的上下沿同时传输数据&#xff0c;我们可以使用IDDR原语将输入的单bit数据转化为2bit的数据输出。同时数据速率变为原来的二分之一…