线程——线程同步
案例:卖票
需求:某电影院目前正在上映国产大片,共有100张票,而它有三个窗口卖票,请设计一个程序模拟该电影院卖票
思路:
定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private in tickets = 100;
在SellTicket类中重写run()方法实现卖票,代码步骤如下
判断票数大于0,就卖票,并告知是那个窗口卖的
卖了票之后,总票数减1
票没了,也可能有人来问,所以这里用死循环让卖票的动作一直执行
定义一个测试类SellTicketDemo,里面有main()方法,代码步骤如下
创建SellTicket类对象
创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
启动线程
package com.aynu14;//定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private in tickets = 100;
public class SellTicket implements Runnable{private int tickets=100;//在SellTicket类中重写run()方法实现卖票,代码步骤如下@Overridepublic void run() {
// 判断票数大于0,就卖票,并告知是那个窗口卖的
// 卖了票之后,总票数减1
// 票没了,也可能有人来问,所以这里用死循环让卖票的动作一直执行while (true){if (tickets>0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");tickets--;}}}
}
package com.aynu14;// 需求:某电影院目前正在上映国产大片,共有100张票,而它有三个窗口卖票,请设计一个程序模拟该电影院卖票
//
// 思路:
// 定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private in tickets = 100;
// 在SellTicket类中重写run()方法实现卖票,代码步骤如下
// 判断票数大于0,就卖票,并告知是那个窗口卖的
// 卖了票之后,总票数减1
// 票没了,也可能有人来问,所以这里用死循环让卖票的动作一直执行
//
// 定义一个测试类SellTicketDemo,里面有main()方法,代码步骤如下
// 创建SellTicket类对象
// 创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
// 启动线程public class SellTicketDemo {public static void main(String[] args) {//创建SellTicket类对象SellTicket st=new SellTicket();//创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称Thread t1=new Thread(st,"窗口1");Thread t2=new Thread(st,"窗口2");Thread t3=new Thread(st,"窗口3");//启动线程t1.start();t2.start();t3.start();}
}
卖票出现了问题
相同的票出现多次
出现了负数的票
问题原因
线程执行的随机性导致的
卖票案例数据安全问题的解决
为什么出现问题?(这也是我们判断多线程程序是否会有数据安全问题的标准)
是否具有多线程环境
是否有共享数据
是否有多条语句操作共享数据
如何解决多线程安全问题
基本思想:让程序没有安全问题的环境
怎么实现呢?
把多条语句操作共享数据的代码锁起来,让任意时刻只能有一个线程执行即可
java提供了同步代码块的方式来解决
锁多条语句操作共享数据,可以使用同步代码块实现
格式:
synchronized(任意对象){
多条语句操作共享数据的代码
}
synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁
同步的好处和弊端
好处:解决了多线程的数据安全问题
弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这里很耗费资源的,无形中会降低程序的运行效率
package com.aynu14;//定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private in tickets = 100;
public class SellTicket implements Runnable{private int tickets=100;private Object obj=new Object();//在SellTicket类中重写run()方法实现卖票,代码步骤如下@Overridepublic void run() {
// 判断票数大于0,就卖票,并告知是那个窗口卖的
// 卖了票之后,总票数减1
// 票没了,也可能有人来问,所以这里用死循环让卖票的动作一直执行//相同票出现了多次
// while (true){
// //tickest=100;
// //t1,t2,t3
// //假设t1线程抢到CPU执行权
// if (tickets>0) {
// //通过Sellp()方法来模拟出票时间
// try {
// Thread.sleep(100);
// //t1线程休息100毫秒
// //t2线程抢到CPU的执行权,t2线程就开始执行,执行到这里的时候,t2线程休息100毫秒
// //t3线程抢到CPU的执行权,t3线程就开始执行,执行到这里的时候,t3线程休息100毫秒
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
// //假设线程按照顺序醒过来
// //t1抢到CPU的执行权,在控制台输出,窗口1正在出售第100张票
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
// //t2抢到CPU的执行权,在控制台输出,窗口2正在出售第100张票
// //t3抢到CPU的执行权,在控制台输出,窗口3正在出售第100张票
// tickets--;
//
// //如果这三个线程还是按照顺序来,这里就执行了3次--操作,最终票就变成了97
// }
// }//出现了负数的票while (true){synchronized (obj) {//tickest=1;//t1,t2,t3//假设t1线程抢到CPU执行权if (tickets > 0) {//通过Sellp()方法来模拟出票时间try {Thread.sleep(100);//t1线程休息100毫秒//t2线程抢到CPU的执行权,t2线程就开始执行,执行到这里的时候,t2线程休息100毫秒//t3线程抢到CPU的执行权,t3线程就开始执行,执行到这里的时候,t3线程休息100毫秒} catch (InterruptedException e) {throw new RuntimeException(e);}//假设线程按照顺序醒过来//t1抢到CPU执行权,在控制台输出,窗口1正在出售第1张票//假设t1继续拥有CPU的执行权,就会执行tickets--操作,ticket=0;//t2抢到CPU执行权,在控制台输出,窗口2正在出售第0张票//假设t2继续拥有CPU的执行权,就会执行tickets--操作,ticket=-1;//t3抢到CPU执行权,在控制台输出,窗口2正在出售第-1张票//假设t3继续拥有CPU的执行权,就会执行tickets--操作,ticket=-2;System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");tickets--;}}}}
}
package com.aynu14;// 需求:某电影院目前正在上映国产大片,共有100张票,而它有三个窗口卖票,请设计一个程序模拟该电影院卖票
//
// 思路:
// 定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private in tickets = 100;
// 在SellTicket类中重写run()方法实现卖票,代码步骤如下
// 判断票数大于0,就卖票,并告知是那个窗口卖的
// 卖了票之后,总票数减1
// 票没了,也可能有人来问,所以这里用死循环让卖票的动作一直执行
//
// 定义一个测试类SellTicketDemo,里面有main()方法,代码步骤如下
// 创建SellTicket类对象
// 创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
// 启动线程public class SellTicketDemo {public static void main(String[] args) {//创建SellTicket类对象SellTicket st=new SellTicket();//创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称Thread t1=new Thread(st,"窗口1");Thread t2=new Thread(st,"窗口2");Thread t3=new Thread(st,"窗口3");//启动线程t1.start();t2.start();t3.start();}
}
同步方法:就是把synchronized关键字加到方法上
格式:
修饰符synchronized返回值类型 方法名(方法参数){ }
同步方法的锁对象是什么呢
this
同步静态方法,就是把synchornized关键字加到静态方法上
格式
修饰符static synchronized返回值类型 方法名(方法参数)
同步静态方法的锁对象是什么呢
类名.class
相关文章:
线程——线程同步
案例:卖票 需求:某电影院目前正在上映国产大片,共有100张票,而它有三个窗口卖票,请设计一个程序模拟该电影院卖票 思路: 定义一个类SellTicket实现Runnable接口,里面定义一个成员变量ÿ…...
安卓录屏使用VirtualDisplay虚拟屏幕;MediaRecorder,媒体录影机;
1.跟截屏一样,判断权限,然后在onActivityResult里面给mediaProjection赋能; 2.初始化录像机: //初始化Recorder录像机 fun initRecorderStart() { //新建Recorder val displayMetrics DisplayMetrics() val width displayMetri…...

Java FileChannel文件的读写实例
一、概述: 文件通道FileChannel是用于读取,写入,文件的通道。FileChannel只能被InputStream、OutputStream、RandomAccessFile创建。使用fileChannel.transferTo()可以极大的提高文件的复制效率,他们读和写直接建立了通道&#x…...

2023 年男生还推荐报计算机专业吗?
计算机专业确实是一个非常热门的专业,就业前景也很广阔。 但是,近些年随着各个大学对计算机专业及其相关专业疯狂扩招,而且每年的毕业人口都在增多,行业是根本容纳不下的,就业竞争力度也急剧上升。因此,选…...
【华为OD机试真题】积木最远距离(相同数字的积木游戏1)(javapython)
相同数字的积木游戏1 知识点数组循环map 时间限制:1s 空间限制:256MB 限制语言:不限 题目描述: 小华和小薇一起通过玩积木游戏学习数学。 他们有很多积木,每个积木块上都有一个数字,积木块上的数字可能相同。 小华随机拿一些积木挨着排成一排,请小薇找到这排积木中数…...

STM32F103RCT6驱动SG90舵机-完成正反转角度控制
一、SG90舵机介绍 SG90是一种微型舵机,也被称为伺服电机。它是一种小型、低成本的直流电机,通常用于模型和机器人控制等应用中。SG90舵机可以通过电子信号来控制其精确的位置和速度。它具有体积小、重量轻、响应快等特点,因此在各种小型机械…...

【4.13(补)】二叉搜索树的遍历、插入、删除
文章目录二叉搜索树的最近公共祖先二叉搜索树中的插入操作删除二叉搜索树中的节点二叉搜索树的最近公共祖先 235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode) 因为二叉搜索树是有序的,第一次找到p和q中间的值,就是最近的公共祖先…...

Web 攻防之业务安全:Callback自定义测试(触发XSS漏洞)
Web 攻防之业务安全:Callback自定义测试 业务安全是指保护业务系统免受安全威胁的措施或手段。广义的业务安全应包括业务运行的软硬件平台(操作系统、数据库,中间件等)、业务系统自身(软件或设备)、业务所提…...
Java访问底层操作系统
native方法定义: 简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机…...

Python 进阶指南(编程轻松进阶):十六、面向对象编程和继承
原文:http://inventwithpython.com/beyond/chapter16.html 定义一个函数,并从几个地方调用它,可以省去复制和粘贴源代码的麻烦。不复制代码是一个很好的实践,因为如果你需要修改它(无论是为了修复一个错误还是添加新特…...

【计算机系统结构】第一章 计算机系统结构基本概念
文章目录第一章 计算机系统结构基本概念1.1 计算机系统结构的概念1.2 计算机体系结构的发展1.3 系统结构中并行性的发展1.4 系统结构的设计1.5 定量分析技术基础第一章 计算机系统结构基本概念 课程内容 A I P S N 工业革命 1.1 计算机系统结构的概念 引言 第一台通用计算机 …...
e2fsprogs logsave Ubuntu 安装失败 unable to make backup link of ‘./usr/bin/chattr‘
最近给服务器从 Ubuntu 18.04 LTS 升级到 20.04 LTS,过程中崩溃,重新尝试执行,提示依赖错误。这时候 apt install 所有的东西都会报错,提示依赖不满足。(这里的报错忘了复制了)执行 apt upgrade 也是一样。…...
在排序数组中查找元素的第一个和最后一个位置(二分查找进阶)
在写这个题目之前需要大家自行看一下我之前写的博客有关二分查找思想,如何判断什么时候使用二分查找以及边界值的确定:二分查找思想力扣实例_徐憨憨!的博客-CSDN博客 题目:给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定…...

1 Nginx跨域配置
跨域问题在之前的单体架构开发中,其实是比较少见的问题,除非是需要接入第三方SDK时,才需要处理此问题。但随着现在前后端分离、分布式架构的流行,跨域问题也成为了每个Java开发必须要懂得解决的一个问题。 跨域问题产生的原因 产…...

ChatGTP如此强大,我们普通人如何利用它来赚钱?
我从效率提升的角度,分享了我这段时间看到的、用到的,以及思考的一些内容。 最近这段时间,我算是密集的学习。不得不说,优质的资料在推特和油管上特别多,看科技大佬的分享真是一种享受。 很多大神也会录制各种详细的…...

常见的九种大数据分析模型
常见的9种大数据分析模型分别为: 事件分析、 属性分析、 渠道分析、 Session分析、 留存分析、 归因分析、 漏斗分析、 路径分析、 分布分析 1、【事件分析】 事件分析,是指用户在 APP、网站等应用上发生的行为,即何人,何时&…...
射频识别(RFID)技术的基本原理、特性、发展和应用
何谓射频识别 随着高科技的蓬勃发展,智能化管理已经走进了人们的社会生活,一些门禁卡、第二代身份证、公交卡、超市的物品标签等,这些卡片正在改变人们的生活方式。其实秘密就在这些卡片都使用了射频识别技术,可以说射频识别已成…...

3.3 二维随机变量条件分布
学习目标: 要学习二维随机变量的条件分布,我可能会采取以下步骤: 复习边缘分布和联合分布:首先需要了解二维随机变量的边缘分布和联合分布的概念以及相应的公式。 复习条件概率:学习条件概率的定义和计算公式&#x…...

Kafka——概述、安装及命令行操作
文章目录一、概述1.1、定义1.2、如何运作?1.3、传统消息队列的应用场景1.4、消息队列的两种模式1.5、Kafka的基础架构二、安装(需要安装zookeeper)三、常用命令行操作3.1、主题命令行操作3.2、生产者命令行操作3.3、消费者命令行操作一、概述…...
怎么控制ERP企业管理系统开发的价格
企业资源规划(ERP)是一种广泛使用的商业软件系统,用于管理企业的各个方面,包括财务、供应链、客户关系、人力资源等等。开发一个适合企业的ERP系统可能是一项昂贵的任务,但控制ERP企业管理系统开发的价格是可行的。以下…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...