多线程(剩余部分)

Day29

多线程(剩余部分)

十二、线程的礼让

Thread.yield();

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

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

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

随机输出:

A:1
B:1
A:2
B:2
A:3
A:4

public class A extends Thread{

	@Override
	public void run() {
		for (int i = 1; i <= 100; i++) {
			System.out.println("A:" + i);
		}
	}
}
public class B extends Thread{

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

十三、线程的合并

t.join(); 合并方法

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

随机输出:(可能情况去理解)

主线程抢到资源直接打印到十,子线程才开始

主线程抢资源到打印到十,子线程也抢到资源打印了一些

主线程抢到资源打印未到十,子线程抢到资源已经打印完

理解图
线程的合并理解图

public class MyThread extends Thread{

	@Override
	public void run() {
		for (int i = 1; i <=200; i++) {
			System.out.println("子线程:" + i);
		}
	}
}
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();
			}
		}
		
	}
}

十四、线程的中断

线程的中断1
public class MyThread extends Thread{
	@Override
	public void run() {
		while(true){
			System.out.println("111");
			System.out.println("222");
			System.out.println("333");
			System.out.println("444");
		}
	}
}
public class Test01 {
	public static void main(String[] args) throws InterruptedException {
		
		//面试题:下列代码的子线程开启后,是否会在3000毫秒就被销毁?
		//答:不一定,因为3000毫秒后主线程才休眠结束,这时会抢CPU资源
		//	  如果立刻抢到,那么子线程就是3000毫秒后销毁
		//	 如果没有抢到CPU资源,那么子线程会继续运行,直到主线程抢到CPU资源
		MyThread t = new MyThread();
		t.start();
		
		Thread.sleep(3000);
		
		t.stop();//立刻停止(缺点:可能会导致功能确实)
		//stop()方法已经过时(有个横杠线)
	}
	
}
线程的中断2

线程run()结束就会死,runn方法死循环就不会死

用变量flag,防止直接死亡,弥补stop的缺点,线程也有相关的方法

public class MyThread extends Thread{

	private boolean flag = true;
	
	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	@Override
	public void run() {
		while(flag){
			System.out.println("111");
			System.out.println("222");
			System.out.println("333");
			System.out.println("444");
		}
	}
}
public class Test01 {
	public static void main(String[] args) throws InterruptedException {
		
		MyThread t = new MyThread();
		t.start();
		
		Thread.sleep(3000);
		
		t.setFlag(false);
		
	}
	
}
线程的中断3

线程也有相关的方法

public class MyThread extends Thread{
	@Override
	public 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");
		}
	}
}
public class Test01 {
	public static void main(String[] args) throws InterruptedException {
		
		MyThread t = new MyThread();
		t.start();
		
		Thread.sleep(3000);
		
		//改变线程状态
		t.interrupt();
	}
	
}

十五、守护线程

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

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

t.setDaemon(true);

注意:

new出来的都是前台线程

Daemon要在线程启动前设置把,不能在线程启动后设置

父类没有抛异常,子类不能抛异常,只能try catch

public class MyThread extends Thread{

	@Override
	public void run() {
		while(true){
			System.out.println("后台线程默默守护着前台线程");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
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);
		}
		
	}
}

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

线程局部变量共享
理解图

线程局部变量共享理解图

共享单个数据
注意:

A类虽然不是线程类

但是A类的对象在线程中调用了println方法

线程1中的A类对象调用了println方法,那么println方法里的Thread.currentThread()就是获取的是线程1对象

线程2中的A类对象调用了println方法,那么println方法里的Thread.currentThread()就是获取的是线程2对象

public class A {

	public void println(){
		Thread t = Thread.currentThread();
		Integer value = Test01.map.get(t);
		System.out.println(t.getName() + "里的A类对象获取了数据:" + value);
	}
}
//B类同理

public class Test01 {
	public static final ConcurrentHashMap<Thread, Integer> map = new ConcurrentHashMap<>();
	
	public static void main(String[] args) {
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				int i = 10;
				
				//存数据
				map.put(Thread.currentThread(), i);
				
				A a = new A();
				B b = new B();
				a.println();//10
				b.println();//10
			}
		},"线程1").start();
		
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				int i = 20;
				
				//存数据
				map.put(Thread.currentThread(), i);
				
				A a = new A();
				B b = new B();
				a.println();//20
				b.println();//20
				
			}
		}, "线程2").start();
		
	}
}

共享多个数据
1.自定义方法解决
public class A {

	public void println(){
		Thread t = Thread.currentThread();
		Data value = Test01.map.get(t);
		System.out.println(t.getName() + "里的A类对象获取了数据:" + value);
	}
}
//B类同理

//数据包类
public class Data {
	
	private int i;
	private String str;
//有参、无参、get、set、toString方法(略)

}

public class Test01 {
	public static final ConcurrentHashMap<Thread, Data> map = new ConcurrentHashMap<>();
	
	public static void main(String[] args) {
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				
				Data data = new Data(10,"xxx");
				
				//存数据
				map.put(Thread.currentThread(), data);
				
				A a = new A();
				B b = new B();
				a.println();//10
				b.println();//10
			}
		},"线程1").start();
		
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				
				Data data = new Data(20,"yyy");
				
				//存数据
				map.put(Thread.currentThread(), data);
				
				A a = new A();
				B b = new B();
				a.println();//20
				b.println();//20
				
			}
		}, "线程2").start();
		
	}
}
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 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);
	}
}
//B类同理

//数据包类
public class Data {
	
	private int i;
	private String str;
//有参、无参、get、set、toString方法(略)
	//保证每个线程里只有一个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{//有数据就set
			data.setI(i);
			data.setStr(str);
		}
		return data;
	}
}

public class Test01 {
	public static final ThreadLocal<Data> local = new ThreadLocal<>();
	
	public static void main(String[] args) {
		
		new Thread(new Runnable() {
			@Override
			public 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();//10
				b.println();//10
			}
		},"线程1").start();
		
		
		new Thread(new Runnable() {
			@Override
			public 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();//20
				b.println();//20
				
			}
		}, "线程2").start();
		
	}
}

十七、线程的生命周期

概念

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.计算任务,一个包含了2万个整数的数组,分拆了多个线程来进行并行计算,最后汇总出计算的结果。

2.铁道部发布了一个售票任务,要求销售1000张票,要求有3个窗口来进行销售,请编写多线程程序来模拟这个效果(该题涉及到线程安全,https://www.jb51.net/article/221008.htm)

i. 窗口001正在销售第1张票

ii. 窗口001正在销售第2张票

iii. 窗口002正在销售第3张票

iv. 。。。

v. 窗口002正在销售第1000张票

涉及到线程安全,要加锁

总结:

1.线程的礼让 – yield
2.线程的合并 – join
3.线程的中断
4.守护线程
5.线程局部变量共享 – 重要

理解ThreadLocal底层原理

6.线程生命周期 — 重要

线程生命周期图

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

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

相关文章

浅谈一下对于DDD模式的理解3

浅谈一下对于DDD模式的理解&#xff0c;相互学习交流&#xff0c;不对之处欢迎大家指正。 在说到DDD(Domain-Driven Design)设计模式之前&#xff0c;先要说下我们在对系统进行架构设时需要遵循的几个原则&#xff1a; 单一职责&#xff08;SRP&#xff09; "单一职责原则…

直播预约丨《袋鼠云大数据实操指南》No.1:从理论到实践,离线开发全流程解析

近年来&#xff0c;新质生产力、数据要素及数据资产入表等新兴概念犹如一股强劲的浪潮&#xff0c;持续冲击并革新着企业数字化转型的观念视野&#xff0c;昭示着一个以数据为核心驱动力的新时代正稳步启幕。 面对这些引领经济转型的新兴概念&#xff0c;为了更好地服务于客户…

文献速递:基于SAM的医学图像分割---阶梯式微调方法,用于整合补充网络的自适应矩估计(SAM)

Title 题目 Ladder Fine-tuning approach for SAM integrating complementary network 阶梯式微调方法&#xff0c;用于整合补充网络的自适应矩估计&#xff08;SAM&#xff09; 01 文献速递介绍 医学图像分割在医疗保健中扮演着至关重要的角色。它旨在使用各种医学成像方式…

MS2574/2574T/2574S高速、四通道差动线路驱动器

品简述 MS2574/MS2574T/MS2574S 是一款高速、低功耗的四通道 差动线路驱动芯片&#xff0c;用于平衡或非平衡的数字数据传输。可 以满足 ANSI TIA/EIA-422-B 和 ITU &#xff08;原 CCITT &#xff09;建议 V.11 的要求。 三态输出可提供用于驱动双绞线或平行双线传输线路等…

公司购买阿里云服务器多少钱一年?199元2核4G5M配置

阿里云服务器ECS u1实例&#xff0c;2核4G&#xff0c;5M固定带宽&#xff0c;80G ESSD Entry盘优惠价格199元一年&#xff0c;性能很不错&#xff0c;CPU采用Intel Xeon Platinum可扩展处理器&#xff0c;购买限制条件为企业客户专享&#xff0c;实名认证信息是企业用户即可&a…

基于机器视觉的太阳能电池片异物遮挡检测含数据集

分享链接见文末 近年来&#xff0c;随着太阳能发电技术的快速发展&#xff0c;太阳能电池片的应用越来越广泛。然而&#xff0c;太阳能电池片在实际运行过程中常常会受到各种异物的遮挡&#xff0c;如树叶、灰尘等&#xff0c;导致发电效率下降甚至损坏设备。因此&#xff0c;…

python 基于 websocket 的简单将视频推流到网页

本来有一台设备是要搞成无线的形式的&#xff0c;设备的摄像头的数据可以在一台局域网连接的平板上查看&#xff0c;因为试着使用 RTMP 推流&#xff0c;感觉延时太大了&#xff0c;而 Webrtc 感觉有太麻烦了&#xff0c;所以一开始看到这篇文章使用 UDP 协议进行推流&#xff…

竞赛 - 基于机器视觉的图像拼接算法

前言 图像拼接在实际的应用场景很广&#xff0c;比如无人机航拍&#xff0c;遥感图像等等&#xff0c;图像拼接是进一步做图像理解基础步骤&#xff0c;拼接效果的好坏直接影响接下来的工作&#xff0c;所以一个好的图像拼接算法非常重要。 再举一个身边的例子吧&#xff0c;…

“比特币跌至8900美元”?逢低买入信号闪现!亚洲投资者需求正持续增长!

3月19日&#xff0c;美股三大指数集体收涨&#xff0c;美联储正在召开为期两天的货币政策会议&#xff0c;周三公布结果&#xff0c;市场普遍预计美联储将按兵不动。 然而&#xff0c;比特币近几日却面临显著的价格回调&#xff0c;昨早再次从6.7万美元水平快速下滑&#xff0c…

学习vue3第九节(新加指令 v-pre/v-once/v-memo/v-cloak )

1、v-pre 作用&#xff1a;防止编译器解析某个特定的元素及其内容&#xff0c;即v-pre 会跳过当前元素以及其子元素的vue语法解析&#xff0c;并将其保持原样输出&#xff1b; 用于&#xff1a;vue 中一些没有指令和插值表达式的节点的元素&#xff0c;使用 v-pre 可以提高 Vu…

【Linux】shell命令运行原理---认识Linux基本指令

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;Linux_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.shell命令以及运行原理 1.1 shell命令 1.2 Linux内核权限 1.3 图示Linux shell和bash的区别 2.认识Linux基本指令 2.1 指令的…

选马桶别再犯错,这7点要注意!福州中宅装饰,福州装修

在众多卫浴品牌中&#xff0c;各种型号尺寸和性能的马桶更是层出不穷&#xff0c;在选购的时候总是陷入难题&#xff0c;那么接下来就给大家讲讲马桶应该怎么选购&#xff1a; ①高效冲水系统&#xff1a;高效的冲水系统&#xff0c;不仅能确保每一次冲洗都干净彻底&#xff0c…

【RabbitMQ】【Docker】基于docker-compose构建rabbitmq容器

本文通过docker-compose构建一个单体的rabbtimq容器。 1&#xff0c;docker、docker-compose环境 首先需要有docker和docker-compose环境&#xff0c;docker安装[1]&#xff0c;docker-compose安装[2]。 通过下列命令确定docker、docker-compose是否安装成功。 [root192 ge…

春暖花开,一起来看看2024年品牌春分海报吧!

春分&#xff08;Vernal equinox&#xff09;已至&#xff0c;春花烂漫、燕子归来、百草回芽。 今天我们要分享的是2024年品牌发布的春分节气海报合集&#xff0c;快来随我们一起感受这昂扬、蓬勃的春意吧! &#xff08;1&#xff09;泸州老窖 &#xff08;2&#xff09;BD…

语义分割基础知识

1、什么是语义分割 目标检测&#xff1a; 检测出图像中目标位置和类别&#xff0c;使用锚框框出目标位置 实例分割&#xff1a; 将前景物体分割开来&#xff0c;并且每一个物体有不同的id&#xff08;颜色&#xff09; 语义分割&#xff1a; 和实例分割相似&#xff0c;但…

nginx介绍及搭建

架构模型 Nginx是由一个master管理进程、多个worker进程组成的多进程模型。master负责管理worker进程&#xff0c;worker进程负责处理网络事件&#xff0c;整个框架被设计为一种依赖事件驱动、异步、非阻塞的模式。 优势&#xff1a; 1、充分利用多核&#xff0c;增强并发处理…

Python快速导入id至json文件(2024.3.19)

Python实现id导入至json文件 2024.3.19 需求分析1、输入数据介绍1.1 三个.txt文件1.1.1 computers.txt&#xff08;计算机&#xff09;1.1.2 cameras.txt&#xff08;摄像头&#xff09;1.1.3 monitors.txt&#xff08;显示器&#xff09; 1.2 单个.xlsx文件 2、实现思路3、Pyt…

软考81-上午题-【面向对象技术3-设计模式】-行为型设计模式01

一、行为型设计模式一览 二、责任链模式 2-1、意图 使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;直到有一个对象处理它为止。 1-2、结构 1-3、代码实现 1-4、适…

基于python的4s店客户管理系统

技术&#xff1a;pythonmysqlvue 一、背景 进入21世纪网络和计算机得到了飞速发展&#xff0c;并和生活进行了紧密的结合。目前&#xff0c;网络的运行速度以达到了千兆&#xff0c;覆盖范围更是深入到生活中的角角落落。这就促使管理系统的发展。网上办公可以实现远程处理事务…

一文带你详解天池电商数据集

行业介绍&#xff1a; 淘系技术部隶属于阿里巴巴新零售技术事业群&#xff0c;支撑淘宝、天猫核心电商以及闲鱼、躺平等创新业务&#xff0c;服务9亿用户&#xff0c;赋能各行业1000万商家。 淘系技术打造了全球领先的线上新零售技术平台&#xff0c;并作为核心技术团队保障了…