Java笔记(死锁、线程通信、单例模式)

news2024/11/17 11:48:12

一、死锁

1.概述

  • 死锁 : 死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法往下执行。
  • 此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
  • 原理 :
    1. 某个线程执行完成,需要先后嵌套锁定两个对象,在这个过程中,先锁定了第一个对象
    2. 另一个线程执行完成也需要先后嵌套锁定两个对象,在这个过程中,先锁定了第二个对象
    3. 第一个线程执行中,要执行到第二个对象的时候,发现第二个对象被锁定,进入等待状态,等待交出锁
    4. 第二个线程执行中,要执行到第一个对象的时候,发现第一个对象也被锁定,也进入等待状态
    5. 此时两个线程都在等待对方交出锁,导致死锁

2.代码实现

public class Thread_01_DeadLock {
	public static void main(String[] args) {
		Object o1=new Object();
		Object o2=new Object();
		Thread t1=new Thread(new T1(o1, o2));
		Thread t2=new Thread(new T2(o1, o2));
		t1.start();
		t2.start();
	}
}
class T1 implements Runnable{
	Object o1;
	Object o2;
	public T1(Object o1,Object o2){
		this.o1=o1;
		this.o2=o2;
	}
	@Override
	public void run() {
		synchronized (o1) {
//			try {//加上睡眠一定死锁
//				Thread.sleep(1000);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
			System.out.println(Thread.currentThread().getName()+"-->T1o1已锁定");
			synchronized (o2) {
				System.out.println(Thread.currentThread().getName()+"-->T1o2已锁定");
			}
		}
		System.out.println("t1执行完成");
	}
}
class T2 implements Runnable{
	Object o1;
	Object o2;
	public T2(Object o1,Object o2){
		this.o1=o1;
		this.o2=o2;
	}
	@Override
	public void run() {
		try {//加上睡眠一定不死锁
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		synchronized (o2) {
			System.out.println(Thread.currentThread().getName()+"-->T2o2已锁定");
			synchronized (o1) {
				System.out.println(Thread.currentThread().getName()+"-->T2o1已锁定");
			}
		}
		System.out.println("t2执行完成");
	}
}

二、线程通信

1.概述

  • Object中的方法
  • wait : 让当前线程进入等待状态(挂起),并释放锁,当被唤醒之后,接着挂起的位置继续执行,假如之前执行了1、2,到3挂起,那么被唤醒后接着执行3
  • notify : 唤醒一个在该对象中挂起的任意一个线程
  • notifyAll : 唤醒在该对象中挂起的所有线程
  • 这几个方法必须出现在加锁的成员方法
  • wait : 如果是无参,则不会自动醒,也可以传入long类型的值,代表毫秒数,多久之后自动醒
  • wait 和 sleep的区别 :
    • sleep : 让当前线程进入睡眠状态, 是静态方法,和是否加锁没有关系,如果在加锁的方法中,也不会释放锁
    • wait : 让当前线程进入挂起等待状态,必须在加锁的成员方法中,另外会释放锁

2.使用方式

public class Thread_03_Wait {
	public static void main(String[] args) throws InterruptedException {
		Num num=new Num();
		Thread t1=new PrintNum(num);
		Thread t2=new PrintNum(num);
		t1.start();
		Thread.sleep(10);//保证t1先执行
		t2.start();
	}
}
class PrintNum extends Thread{
	Num num;
	public PrintNum(Num num){
		this.num=num;
	}
	@Override
	public void run() {
		while (true) {
			num.printNums();
		}
	}
}
class Num{
	private int count =1;
	public synchronized void printNums(){
		System.out.println(Thread.currentThread().getName()+"-->"+count);
		count++;
		// 唤醒等待的进程
		this.notifyAll();
		try {
			Thread.sleep(1000);
			// 进入挂起状态,并释放锁
			this.wait();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

3.生产者消费者

在这里插入图片描述

3.1.示例

public class Thread_04_Producer {
	public static void main(String[] args) {
		SynStack ss=new SynStack();
		Thread producer1=new Thread(new Producer(ss));
		Thread producer2=new Thread(new Producer(ss));
		Thread consumer1=new Thread(new Consumer(ss));
		Thread consumer2=new Thread(new Consumer(ss));
		producer1.start();
		producer2.start();
		consumer1.start();
		consumer2.start();
	}
}
class Producer implements Runnable{
	private SynStack ss;
	public Producer(SynStack ss){
		this.ss=ss;
	}
	@Override
	public void run() {
		for (int i = 0; i < 26; i++) {
			ss.push((char)('a'+i));
		}
	}
}
class Consumer implements Runnable{
	private SynStack ss;
	public Consumer(SynStack ss){
		this.ss=ss;
	}
	@Override
	public void run() {
		for (int i = 0; i < 26; i++) {
			ss.pop();
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
//业务类
class SynStack{
	int count=0;// 货物数量
	char[] data=new char[6];// 记录货物数量
	// 生产货物
	public synchronized void push(char ch){
		// 判断货物满没满
		while(count ==data.length){//
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		//仓库空了该生产了,此时应该唤醒挂起的消费者
		if (count==0) {
			this.notifyAll();
		}
		data[count++]=ch;
		System.out.println(Thread.currentThread().getName()+"生产了 "+ch+" 还剩 "+count+" 个货物");
	}
	// 消费货物
	public synchronized char pop(){
		// 判断货物空没空
		while(count ==0){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		//仓库满了该挂起了,此时应该唤醒挂起的生产者
		if (count==data.length) {
			this.notifyAll();
		}
		char ch=data[--count];
		System.out.println(Thread.currentThread().getName()+"消费了 "+ch+" 还剩 "+count+" 个货物");
		return ch;
	}
}

三、单例模式

public class SingLeton {
	private SingLeton(){
		
	}
	// volatile 防止指令重排
	private volatile static SingLeton singLeton;
	public static SingLeton getInstance(){
        // 多线程可能同时进入
		if (singLeton==null) {
            // 一个线程进入
			synchronized (SingLeton.class) {
				if (singLeton==null) {
                    // 一个线程进入后 对象就不再是null,其他的线程将无法进入
					singLeton=new SingLeton();
				}	
			}
		}
		return singLeton;
	}
}

四、线程池

  • 线程池的作用:
    • 线程池作用就是限制系统中执行线程的数量。
  • 根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;
  • 少了浪费了系统资源,多了造成系统拥挤效率不高。
  • 用线程池控制线程数量,其他线程排队等候。
  • 一个任务执行完毕,再从队列的中取最前面的任务开始执行。
  • 若队列中没有等待进程,线程池的这一资源处于等待。
  • 当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了,否则进入等待队列。
  • 为什么要用线程池:
    1. 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
    2. 可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)

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

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

相关文章

前端面试题-js-new关键字-this指向-js事件流-防抖节流

前端面试题-js-new关键字-this指向-js事件流-防抖节流 new 关键字都做了什么 this指向问题JS事件流防抖节流函数 new 关键字都做了什么 this指向问题 1.创建一个简单的空对象 2.原型的绑定&#xff0c;确定对象O的原型链 3.绑定this对象为O&#xff0c;传入参数&#xff1b;执…

深入理解旅游网站开发:Java+SpringBoot+Vue+MySQL的实战经验

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

RocketMQ源码阅读-九-自定义过滤规则Flitersrv

RocketMQ源码阅读-九-自定义过滤规则Flitersrv 什么是FiltersrvFiltersrv注册到Broker过滤类Consumer发起订阅设置过滤类代码Consumer上传过滤类代码Flitersrv编译过滤类代码 过滤消息Consumer 从 Filtersrv 拉取消息Flitersrv从Broker拉取消息 Flitersrv的高可用总结 什么是Fi…

电容主要特点和作用,不同类型的电容区别

电容 两个相互靠近的金属板中间夹一层绝缘介质组成的器件&#xff0c;当两端存在电势差时&#xff0c;由于介质阻碍了电荷移动而累积在金属板上&#xff0c;衡量金属板上储存电荷的能力称之为电容&#xff0c;相应的器件称为电容器。 电容&#xff08;Capacitance&#xff09…

PyTorch 中的nn.Conv2d 类

nn.Conv2d 是 PyTorch 中的一个类&#xff0c;代表二维卷积层&#xff08;2D Convolution Layer&#xff09;。这个类广泛用于构建卷积神经网络&#xff08;CNN&#xff09;&#xff0c;特别是在处理图像数据时。 基本概念 卷积: 在神经网络的上下文中&#xff0c;卷积是一种特…

关于mysql默认禁用本地数据加载的情况处理(秒解决)

1.首先报错信息&#xff1a;ERROR 3948 (42000): Loading local data is disabled; this must be enabled on both the client and server sides 2.排查问题&#xff1a; 先检查local_infile的状态&#xff1a;使用sql指令 show global variables like local_infile; 这种情…

Keycloak - docker 运行 前端集成

Keycloak - docker 运行 & 前端集成 这里的记录主要是跟我们的项目相关的一些本地运行/测试&#xff0c;云端用的 keycloak 版本不一样&#xff0c;不过本地我能找到的最简单的配置是这样的 docker 配置 & 运行 keycloak keycloak 有官方(Red Hat Inc.)的镜像&#…

如何在ubuntu22.04安装ROS2

ubuntu22.04安装ROS2 教程 选择对应版本进行安装设置编码添加源安装ROS2设置环境变量 运行ROS2 选择对应版本 通过官方网站&#xff0c;查询Ubuntu与ros对应的版本&#xff0c;版本不一致也会出现安装不成功。 https://wiki.ros.org/ROS/Installation 每一个都可以进行点击&a…

Windows10上使Git Bash支持rsync命令操作步骤

rsync命令是linux上常用的工具之一&#xff0c;用于远程以及本地系统中拷贝/同步文件和文件夹。 Windows Git Bash默认并不支持rsync&#xff0c;如下图所示&#xff1a; 使Git Bash支持rsync命令操作步骤&#xff1a; 1.从https://repo.msys2.org/msys/x86_64/ 下…

flutter-相关个人记录

1、flutter 安卓打包打包报错 flutter build apk -v --no-tree-shake-icons 2、获取华为指纹证书命令 keytool -list -v -keystore ***.jks 3、IOS项目中私有方法查找隐藏文件中 1、cd 项目目录地址 2、grep -r xerbla. "xerbla"为需要查找的关键字 3…

在IDEA中创建SpringBoot项目

概述 SpringBoot是由Pivotal团队提供的全新的框架&#xff0c;其设计的目的是用来简化Spring应用的初始搭建以及开发过程。 传统方式构建Spring应用程序 导入依赖繁琐 依赖冲突 项目配置繁琐 SpringBoot特性 1、起步依赖 本质上就行一个Maven坐标&#xff0c;整合了完成一…

RockChip DRM Display Driver

资料来源: 《Rockchip_DRM_Display_Driver_Development_Guide_V1.0.pdf》 《Rockchip_Developer_Guide_DRM_Display_Driver_CN.pdf》 一:DRM概述 DRM(Direct Rendering Manager)直接渲染管理,buffer分配,帧缓冲。对应userspace库位libdrm,libdrm库提供了一系列友好的…

【NeRF】了解学习Neural Radiance Fields(神经辐射场)

文章目录 1.Definition of field&#xff08;场的定义&#xff09;1.1 shape representations&#xff08;各种形状表征方式&#xff09;1.2 Explicit surfaces and implicit surfaces1.3 Radiance Field(Implicit Surfaces)体素密度 2.Definition of Rendering&#xff08;渲染…

项目解决方案:非执法视频监控系统项目设计方案

目 录 一、概述 &#xff08;一&#xff09;前言 &#xff08;二&#xff09;设计思路 &#xff08;三&#xff09;设计原则 1、实用性 2、可靠性 3、安全性 4、先进性 5、开放性 6、易管理、易维护 &#xff08;四&#xff09;设计依据 二、方案总…

数据可视化的未来:2024 年及以后_光点科技

随着我们进入数据驱动决策的下一个时代&#xff0c;数据可视化领域即将迎来一场变革性革命。随着信息的不断涌入和数据的复杂性不断增加&#xff0c;传统的可视化方法需要帮助跟上步伐。人工智能、机器学习和增强现实等新兴技术正在为新一代实时数据可视化工具铺平道路&#xf…

C语言-算法-线性dp

[USACO1.5] [IOI1994]数字三角形 Number Triangles 题目描述 观察下面的数字金字塔。 写一个程序来查找从最高点到底部任意处结束的路径&#xff0c;使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。 在上面的样例中&#xff0c;从 7 → 3 → 8 →…

centos手动下载配置redis并自启动

有些服务器不能自动安装配置redis&#xff0c;仓库找不到之类的问题&#xff0c;就需要手动下载配置redis&#xff0c;记录下&#xff0c;方便以后使用&#xff08;ps&#xff0c;如果报错可能是gcc缺失&#xff09; 1、下载 Redis 源码包&#xff1a;访问 Redis 官网或可信的…

前端学习生产环境、开发环境、测试环境

1、路径 定义是什么环境 NODE_ENVdevelopment 开发环境 2、.env 端口号 3、.env.development 开发环境 4、.env.production 生产环境 5、.env.test 测试环境 6、如何访问&#xff0c;通过process.env进行访问 学习中.......

acrobat调整pdf的页码和实际页码保持一致

Acrobat版本 具体操作 现在拿到pdf的结构如下&#xff1a; pdf页码实际页码1-10页无页码数11页第1页 操作&#xff0c;选择pdf第10页&#xff0c;右键点击 具体设置 最终效果

视频渲染靠cpu还是显卡 会声会影视频渲染的作用是什么

视频渲染最占用的资源就是CPU&#xff0c;多核心多线程&#xff0c;这样才能渲染快。渲染可以在时间线上实时平滑预览&#xff0c;便于编辑&#xff0c;最终导出成片的时候速度也会快一些&#xff0c;渲染就是对每桢的图像进行重新优化的过程。 渲染的作用主要是能够保证使用者…