多线程实现方式二

这里写目录标题

  • Runnable
    • Runable接口实现多线程
    • 使用Runnable接口实现多线程的好处
    • 线程同步 - 三个窗口买票
    • lock实现同步锁

Runnable

Runable接口实现多线程

  • 实现 Runnable 接口

    • 定义一个类 MyRunnable 实现 Runnable 接口

    • 在 MyRunnable 类中重写 run() 方法

    • 创建 Thread 类的对象,把 MyRunnable 对象作为构造方法的参数

    • 启动线程

demo:

定义一个类作为Runnable接口实现类

package com.itxs.demo05;/*** @Classname : MyRunnable* @Description : TODO* @Author : lin_refuel@qq.com*/
public class MyRunnable implements Runnable {@Overridepublic void run() {for (int i = 0; i < 20; i++) {System.out.println(Thread.currentThread().getName() + " i = " + i);}}
}

测试类demo01

package com.itxs.demo05;/*** @Classname : demo01* @Description : TODO* @Author : lin_refuel@qq.com*/
public class demo01 {public static void main(String[] args) {MyRunnable mr = new MyRunnable();//创建线程Thread mt01 = new Thread(mr, "线程01");//Runnable接口实现类对象作为参数进行传递Thread mt02 = new Thread(mr, "线程02");Thread mt03 = new Thread(mr, "线程03");//匿名内部类方式实现new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 30; i++) {System.out.println(Thread.currentThread().getName()+" i = " + i);}}},"匿名线程").start();// 线程开启mt01.start();mt02.start();mt03.start();}
}

使用Runnable接口实现多线程的好处

  • 相比继承 Thread 类,实现 Runnable 接口的好处

    • 避免了 Java 单继承的局限性

    • 适合多个程序的代码同时处理一个资源的情况,把线程和程序的代码、数据有效的分离,较好的体现了面向对象程序设计的思想

线程同步 - 三个窗口买票

需求:德云社封箱演出共有 100 张门票,设置三个窗口买票,设计模拟买票的程序

思路:

  1. 定义一个 SellTickets 实现 Runnable 接口,里面定义一个成员:private int tickets = 100;

  2. 在 SellTickets 类中重写 run() 方法,实现买票

    1. 判断剩余票数是否大于 0,是就卖,并告知是哪个窗口卖出的

    2. 卖掉一张之后要对应减一

    3. 没有票了,也可能有人来买,用死循环让买票动作一直持续

  3. 顶一个测试类 SellTicketsTest,里面有 main() 方法

    1. 创建 SellTickets 类对象

    2. 创建三个 Thread 类的对象,把 SellTickets 对象作为构造方法的参数,并给出对应的窗口名称

    3. 启动线程

sycnchronized(任意对象){}:同步语句块,多个线程操作同一个资源时,当某个线程执行同步语句块里面的代码时,别的线程是无法执行的,只有当执行同步语句块线程执行完里面同步语句块的内容时,其他线程才能进行访问

  • 是否有多线程环境

  • 是否有共享数据

  • 是否有多条语句操作共享项数据

参考文章

demo:

卖票的动作,注意同步语句块的用法

package com.itxs.demo06;/*** @Classname : SellTickets* @Description : TODO* @Author : lin_refuel@qq.com*/
public class SellTickets implements Runnable {private int tickets = 100;// 门票数量为100@Overridepublic void run() {// 定义死循环,一直进行买票while (true){// 同步语句块,一个窗口抢到卖票权,其他窗口无法卖出同一个票synchronized (this){// 判断门票数是否大于0满足条件进行卖票if(tickets > 0){//打印出票System.out.println(Thread.currentThread().getName() +"正在买第 - "+this.tickets+"张门票");// 每次打印出票后,票数减去1this.tickets --;}}// 每个窗口卖出票后,等待出票try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

test测试类

package com.itxs.demo06;/*** @Classname : test* @Description : TODO 测试类* @Author : lin_refuel@qq.com*/
public class test {public static void main(String[] args) {//创建卖票动作的线程SellTickets st = new SellTickets();// 创建三个窗口进行买票Thread windows01 = new Thread(st, "窗口1");Thread windows02 = new Thread(st, "窗口2");Thread windows03 = new Thread(st, "窗口3");// 开始买票windows01.start();windows02.start();windows03.start();}
}

lock实现同步锁

还是上面的案例,通过lock方式实现线程同步

买票的类

package com.itxs.demo06;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @Classname : SellTickets* @Description : TODO* @Author : lin_refuel@qq.com*/
public class SellTickets implements Runnable {private int tickets = 100;// 门票数量为100private  Lock lock = new ReentrantLock();@Overridepublic void run() {// 定义死循环,一直进行买票while (true){// 同步语句块,一个窗口抢到卖票权,其他窗口无法卖出同一个票ticket();// 每个窗口卖出票后,等待出票try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}// 同步方法private /*synchronized*/ void ticket() {//synchronized (this){lock.lock();//上锁// 判断门票数是否大于0满足条件进行卖票if(this.tickets > 0){//打印出票System.out.println(Thread.currentThread().getName() +"正在买第 - "+this.tickets+"张门票");// 每次打印出票后,票数减去1this.tickets --;}//}lock.unlock();//开锁,!!!注意不要忘记开锁}
}

test测试类

package com.itxs.demo06;/*** @Classname : test* @Description : TODO 测试类* @Author : lin_refuel@qq.com*/
public class test {public static void main(String[] args) {//创建卖票动作的线程SellTickets st = new SellTickets();// 创建三个窗口进行买票Thread windows01 = new Thread(st, "窗口1");Thread windows02 = new Thread(st, "窗口2");Thread windows03 = new Thread(st, "窗口3");// 开始买票windows01.start();windows02.start();windows03.start();}
}

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

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

相关文章

Python系列(3)—— 变量

变量 一、变量命名规范二、变量赋值三、变量的数据类型四、变量的作用域五、变量类型转换 Python编程中&#xff0c;变量是存储数据的容器。它们用于存储各种数据类型&#xff0c;如整数、浮点数、字符串、列表、字典等。理解变量及其工作原理是Python编程的基础。 一、变量命…

在Android原生项目中 创建 Flutter模块

前言 应用场景&#xff1a;在已有的Android原生项目中&#xff0c;引入Flutter模块&#xff0c;摸索了两天&#xff0c;终于给整出来了&#xff1b; 如果是新项目&#xff0c;最好直接创建Flutter项目&#xff0c;然后在Fluter的 android / ios目录中&#xff0c;写原生代码&…

深思熟虑可能性模型介绍与使用

深思熟虑可能性模型介绍与使用 如何联系我 作者&#xff1a;鲁伟林 邮箱&#xff1a;thinking_fioa163.com或vlinyes163.com 版权声明&#xff1a;文章和记录为个人所有&#xff0c;如果转载或个人学习&#xff0c;需注明出处&#xff0c;不得用于商业盈利行为。 背景 20…

力扣27-移除元素

移除元素 题目链接 解题思路 ans为左指针 循环遍历为右指针 右指针开始遍历整个列表&#xff0c;如果指针所指的元素与val值不等&#xff0c;那么这个元素不能被删除&#xff0c;将其放入到左指针索引处。 因为return的是列表的长度&#xff0c;ans恰好也是删除完元素后列表的…

[牛客周赛复盘] 牛客周赛 Round 28 20240114

[牛客周赛复盘] 牛客周赛 Round 28 20240114 总结A\B1. 题目描述2. 思路分析3. 代码实现 小红的炸砖块1. 题目描述2. 思路分析3. 代码实现 小红统计区间&#xff08;easy&#xff09;1. 题目描述2. 思路分析3. 代码实现 小红的好数组1. 题目描述2. 思路分析3. 代码实现 小红统…

FX图中的节点代表什么操作

在 FX 图中&#xff0c;每个节点代表一个操作。这些操作可以是函数调用、方法调用、模块实例调用&#xff0c;也可以是 torch.nn.Module 实例的调用。每个节点都对应一个调用站点&#xff0c;如运算符、方法和模块。 一.节点操作 下面是一些节点可能代表的操作&#xff1a; 1…

js中的数据类型

JavaScript 中有以下几种常见的数据类型&#xff1a; 基本类型&#xff08;原始类型&#xff09;&#xff1a; 字符串&#xff08;String&#xff09;&#xff1a;表示文本数据。数字&#xff08;Number&#xff09;&#xff1a;表示数值数据。布尔&#xff08;Boolean&#xf…

PPT插件-大珩助手-保留原素材的位置和大小一键替换

保留原素材的位置和大小一键替换 若勾选了一键替换&#xff0c;对于从素材库插入的图形&#xff0c;可以使得它的位置、大小与幻灯片中选中的形状一致 软件介绍 PPT大珩助手是一款全新设计的Office PPT插件&#xff0c;它是一款功能强大且实用的PPT辅助工具&#xff0c;支持W…

在众多的材质中选择灰口铸铁铸造划线平台、铸铁平台等的原因——河北北重

使用灰口铸铁制作铸铁平台和划线平台的主要原因有以下几点&#xff1a; 强度高&#xff1a;灰口铸铁具有较高的强度和硬度&#xff0c;能够承受较大的载荷和冲击力。这使得灰口铸铁非常适合制作需要承受重压和磨损的平台和设备。 耐磨性好&#xff1a;灰口铸铁具有较高的耐磨性…

对于计算机考研的个人攻略

对于计算机考研的个人攻略 一&#xff1a;专业课复习 ​ 首先从时间上来说&#xff0c;对专业课的复习是在数学基础部分看完以后&#xff0c;这个时候是数学题目和专业课同步进行的。 这里我们按照 408 的划分来复习 408 分数占比为&#xff1a; 数据结构 45 分 计算机组成…

MySQL的多版本并发控制(MVCC)

MVCC MVCC&#xff0c;是Multiversion Concurrency Control的缩写&#xff0c;翻译过来是多版本并发控制&#xff0c;和数据库锁样&#xff0c;他也是一种并发控制的解决方案 我们知道&#xff0c;在数据库中&#xff0c;对数据的操作主要有2种&#xff0c;分别是读和写&…

MetaGPT学习笔记 - task1task2

章节&#xff1a;task1&task2 一.github地址&#xff1a;github.com/geekan/MetaGPT 二.MetaGPT: 多智能体框架​ 使 GPT 以软件公司的形式工作&#xff0c;协作处理更复杂的任务 MetaGPT输入一句话的老板需求&#xff0c;输出用户故事 / 竞品分析 / 需求 / 数据结构 / A…

1115: 数组最小值(数组)

题目描述 数组a有n个元素&#xff0c;请输出n个元素的最小值及其下标。若最小值有多个&#xff0c;请输出下标最小的一个。注意&#xff0c;有效下标从0开始。 输入 输入分两行&#xff0c;第一行是一个正整数n&#xff08;n<1000)&#xff0c;第二行是n个整数。 输出 …

出现 SyntaxError: future feature annotations is not defined 解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 执行sql语句的时候,出现如下问题,问题如下所示: E:\software\anaconda3\envs\py3.6\python.exe F:\python_project\test\sql_connect.py Traceback (most recent call last):File "F:\python_project\test\sql_c…

机器学习之Ridge回归与Lasso回归

Ridge回归与Lasso回归是什么 Ridge回归和Lasso回归是机器学习中常用的线性回归算法的变种。 Ridge回归是一种线性回归算法&#xff0c;通过在损失函数中添加一个正则化项&#xff0c;以控制模型的复杂度。正则化项是模型参数的平方和与一个参数alpha的乘积&#xff0c;alpha越…

行程长度编码

前言 NWAFU 2023阶段二 A 一、题目描述 题目描述 “行程长度编码&#xff08;Run-Length Encoding&#xff0c;RLE&#xff09;”是一种无损压缩编码方法&#xff0c;其核心思想是依次记录符号序列中的每个字符&#xff08;忽略大小写&#xff09;及其重复出现的次数。例如用…

Makefile编译原理 变量的使用

一.变量和不同的赋值方法 ->makefile中支持程序设计语言中变量的概念 ->makefile中的变量只代表文本数据&#xff08;字符串&#xff09; ->makefile中的变量名规则 - 变量名可以包含字符&#xff0c;数字&#xff0c;下划线。 - 不能包含 ":" "#&…

C++重点简答题

文章目录&#xff08;持续更新&#xff09; C重点简答题&#x1f4e3;一、什么是静态变量&#xff1f;&#x1f4e3;二、谈谈你对顺序文件的认识&#xff1f;&#x1f4e3;三、什么是局部变量&#xff1f;什么是全局变量&#xff1f;二者的区别&#xff1f;&#x1f4e3;四、谈…

你好2024,OpenStreetMap 20 周岁

2004年&#xff0c;OpenStreetMap在英国诞生。2024年&#xff0c;OpenStreetMap 满 20 周岁&#xff0c;其愿景是创建一个免费的、可编辑的世界地图。当时&#xff0c;地图数据的获取往往受到限制或价格昂贵1。 经过20年的发展&#xff0c;该数据集合成为了最为全面的街道级别开…

宿舍维修管理系统:从数据库到前端的全面解析

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