卖票案例

5个窗口同时卖票:
使用Runnable接口,只创建了一个ticket1对象,5个线程共享此对象,实现了资源共享。

public class ticket1 implements Runnable {private  int ticket = 5;@Overridepublic void run(){for (int i = 0; i < 10; i++) {if(ticket > 0){System.out.println(Thread.currentThread().getName()+"正在出售第"+(ticket--)+"张票");}}}public static void main(String[] args) {ticket1 ticket1 = new ticket1();Thread t1 = new Thread(ticket1);Thread t2 = new Thread(ticket1);Thread t3 = new Thread(ticket1);Thread t4 = new Thread(ticket1);Thread t5 = new Thread(ticket1);t1.start();t2.start();t3.start();t4.start();t5.start();}}

输出:

Thread-1正在出售第5张票
Thread-2正在出售第3张票
Thread-0正在出售第4张票
Thread-3正在出售第1张票
Thread-1正在出售第2张票

问题:
售票的顺序不对,应该以售出第5 - 4 - 3 - 2 - 1 张票的顺序

解决方法
1. 使用同步代码块

public class ticketSyn1 implements Runnable {

private int ticket = 5;@Override
public void run() {for (int i = 0; i < 10; i++) {synchronized (this) {if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票");}}try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}
}public static void main(String[] args) {ticketSyn1 ticket1 = new ticketSyn1();Thread t1 = new Thread(ticket1, "A");Thread t2 = new Thread(ticket1, "B");Thread t3 = new Thread(ticket1, "C");Thread t4 = new Thread(ticket1, "D");Thread t5 = new Thread(ticket1, "E");t1.start();t2.start();t3.start();t4.start();t5.start();
}
  1. 使用同步方法
public class ticketSyn2 implements Runnable {private int ticket = 5;@Overridepublic void run() {for (int i = 0; i < 10 ; i++) {this.sell();try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized void sell(){if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票");}}public static void main(String[] args) {ticketSyn2 ticket1 = new ticketSyn2();Thread t1 = new Thread(ticket1, "A");Thread t2 = new Thread(ticket1, "B");Thread t3 = new Thread(ticket1, "C");Thread t4 = new Thread(ticket1, "D");Thread t5 = new Thread(ticket1, "E");t1.start();t2.start();t3.start();t4.start();t5.start();}}

总结
同步代码块中的 synchronized(obj){}中的obj可为任何对象,推荐使用共享资源作为同步监视器。

练习

需求说明
张三和妻子各拥有一张银行卡和存折,可以对同一个银行账户迚行存取款的操作,请使用多线程及同步方法模拟张三和妻子同时取款的过程。要求使用同步方法和同步代码块两种方式实现

分析
定义Account类表示银行帐户
定义两个线程分别实现张三和妻子取款的操作

public class Account implements Runnable{private float money;public Account(){};public Account(float money) {this.money = money;}public float getMoney() {return money;}public void setMoney(float money) {this.money = money;}@Overridepublic void run() {for (int i = 0; i < 5; i++) {this.withdraw(400);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized void withdraw(float withdrawMoney){System.out.println(Thread.currentThread().getName()+"正在取款");if(money >= withdrawMoney){money = money - withdrawMoney;System.out.println(Thread.currentThread().getName()+"取款成功!余额为"+money);}else {System.out.println("余额不足!取款失败。余额为"+money);}}public static void main(String[] args) {Account account = new Account(2000);Thread t1 = new Thread(account,"张三");Thread t2 = new Thread(account,"张三妻子");t1.start();t2.start();}
}

输出:

张三正在取款
张三取款成功!余额为1600.0
张三妻子正在取款
张三妻子取款成功!余额为1200.0
张三正在取款
张三取款成功!余额为800.0
张三妻子正在取款
张三妻子取款成功!余额为400.0
张三正在取款
张三取款成功!余额为0.0
张三妻子正在取款
余额不足!取款失败。余额为0.0
张三正在取款
余额不足!取款失败。余额为0.0
张三妻子正在取款
余额不足!取款失败。余额为0.0
张三正在取款
余额不足!取款失败。余额为0.0
张三妻子正在取款
余额不足!取款失败。余额为0.0

死锁

同步可以保证资源共享操作的正确性,但是过多同步也会产生死锁。

死锁一般情况下表示相互等待,是程序运行时出现的一种文体

线程通信

Java提供了3 种方法解决线程间的通信问题:

void notify()
Wakes up a single thread that is waiting on this object’s monitor.
唤醒一个处于等待状态的线程

void notifyAll()
Wakes up all threads that are waiting on this object’s monitor.
唤醒所有处于等待状态的线程

void wait()
Causes the current thread to wait until it is awakened, typically by being notified or interrupted.
使此线程一直等待,直到它被其他线程通知

void wait​(long timeoutMillis)
Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.
指定等待的毫秒时间

void wait​(long timeoutMillis, int nanos)
Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real
指定等待的毫秒、微秒时间

生产者与消费者案例

商品类:

public class Goods {private String brand;private String name;//默认最初无商品, flag = falseprivate boolean flag = false;public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public String getName() {return name;}public void setName(String name) {this.name = name;}public synchronized void get(){//flag == false 说明无商品,消费者线程等待,进入阻塞状态。if(!flag){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("消费者购买了"+this.getBrand()+this.getName());flag = false;//唤醒生产者线程进行生产notify();}public synchronized void set(String brand,String name){// flag == true 说明有商品,生产者线程等待,进入阻塞状态。if(flag){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}this.setName(name);this.setBrand(brand);System.out.println("生产者生产了"+this.getBrand()+this.getName());flag = true;//唤醒消费者去购买notify();}}

生产者类:

public class Producer implements Runnable{private Goods goods;public Producer(Goods goods){this.goods = goods;}@Overridepublic void run() {for (int i = 0; i < 10 ; i++) {if(i%2==0){goods.set("娃哈哈","矿泉水");goods.set("旺仔","牛奶");}}}
}

消费者类:

public class Consumer implements Runnable{private Goods goods;public Consumer(Goods goods) {this.goods = goods;}@Overridepublic void run() {for (int i = 0; i < 10 ; i++) {goods.get();}}
}

测试类:

public class Test {public static void main(String[] args) {Goods goods = new Goods();Producer producer = new Producer(goods);Consumer consumer = new Consumer(goods);Thread t1 = new Thread(producer);Thread t2 = new Thread(consumer);t1.start();t2.start();}
}

输出:

生产者生产了娃哈哈矿泉水
消费者购买了娃哈哈矿泉水
生产者生产了旺仔牛奶
消费者购买了旺仔牛奶
生产者生产了娃哈哈矿泉水
消费者购买了娃哈哈矿泉水
生产者生产了旺仔牛奶
消费者购买了旺仔牛奶
生产者生产了娃哈哈矿泉水
消费者购买了娃哈哈矿泉水
生产者生产了旺仔牛奶
消费者购买了旺仔牛奶
生产者生产了娃哈哈矿泉水
消费者购买了娃哈哈矿泉水
生产者生产了旺仔牛奶
消费者购买了旺仔牛奶
生产者生产了娃哈哈矿泉水
消费者购买了娃哈哈矿泉水
生产者生产了旺仔牛奶
消费者购买了旺仔牛奶

多线程:线程同步与死锁(卖票案例)、线程通信、生产者与消费者相关推荐

  1. java线程同步的死锁_Java基础之线程5-线程同步死锁

    死锁:线程之间因条件相互竞争,导致线程都不能正常执行完,从而产生了死锁. 死锁的例子: public class TestDeadLock implements Runnable { public i ...

  2. Java 线程同步与死锁 学习笔记

    Java 线程同步与死锁 学习笔记 Java 线程同步与死锁 学习笔记 1 多线程共享数据 2 线程同步 3 同步准则 4 线程死锁 1. 多线程共享数据 在多线程操作中,多个线程可能同时处理同一个资 ...

  3. 【Java 并发编程】多线程、线程同步、死锁、线程间通信(生产者消费者模型)、可重入锁、线程池

    并发编程(Concurrent Programming) 进程(Process).线程(Thread).线程的串行 多线程 多线程的原理 多线程的优缺点 Java并发编程 默认线程 开启新线程 `Ru ...

  4. 卖票案例 多线程 java 1615387415

    卖票案例 多线程 java 1615387415 解决 线程类 测试类 注意,需要给线程的类添加带参构造方法 在带参构造方法中 调一下父类的带参构造方法 最终结果 每个窗口都卖了一百张票

  5. Java线程安全(卖票案例) 如何解决线程安全(synchronized ,显示锁Lock)

    文章目录 线程安全 解决方法: 1.同步代码块 2.同步方法 3.显示锁 显示锁与隐式锁的区别 4.公平锁与非公平锁 线程安全 经典问题:卖票问题,多个线程一起执行该任务,当余票只有1一张时,三个线程 ...

  6. Java多线程(卖票案例)

    1.卖票案例需求分析 某天某个景区售票,门票票只有100张,景区有三个售票窗口,同时售票,共享票源(100张) 通过多线程的方式实现三个售票窗口同时售票 首先要明确票源只能有一个 其次需要创建三个Th ...

  7. java多线程,卖票案例

    目录 卖票案例 测试代码 代码1 代码2,卖票问题的思考 代码3 代码4 代码5 卖票案例 测试代码 package com.itheima_06;/*需求:某电影院目前正在上映国产大片,共有100张 ...

  8. c++ linux 线程等待与唤醒_Linux线程同步(互斥量、信号量、条件变量、生产消费者模型)...

    为什么要线程同步? 线程间有很多共享资源,都对一个共享数据读写操作,线程操作共享资源的先后顺序不确定,可能会造成数据的冲突 看一个例子 两个线程屏行对全局变量count++ (采用一个val值作为中间 ...

  9. DLL内线程同步主线程研究(子线程代码放到主线程执行)

    DLL内线程同步主线程研究(子线程代码放到主线程执行) 我们在实际项目中经常会用到多线程编程,比如Socket编程等,在创建的线程内同步主线程一般使用Synchronize方法实现子线程操作放到主线程 ...

最新文章

  1. vnx vmax分盘过程
  2. android log时间,android – Logcat的日志时间戳不按顺序排列
  3. 动态代理以及对应Spring中AOP源码分析
  4. Java 工具集 Hutool 4.0.8 发布
  5. docker安装mysql并配置,Docker安装MySql-挂载外部数据和配置
  6. 酷狗音乐在线试听下载
  7. flask 开发接口测试平台
  8. Android Service学习之IntentService 深入分析
  9. 真相了!AI 程序员:我们根本没有 80w 年薪好么?
  10. tomcat配置重定向_在Tomcat上配置SSL以及从HTTP到HTTPS的设置自动重定向的步骤
  11. nginx编译和调试
  12. swiper 插件里面嵌套可滚动内容
  13. unity给头发添加物理_U3D实时渲染教程之角色头发各向异性表达(上)
  14. MySQL索引的详细分析和数据结构
  15. Python 文件打开读取写入方法
  16. Python PaddleNLP实现自动生成虎年藏头诗
  17. kingcms 5.0 漏洞
  18. Mars3D之三维空间视角
  19. 工作流(1):表格设计
  20. X-Files 目录及剧情简介

热门文章

  1. 夏天水果店损耗怎么控制,夏天水果店怎么减少损耗
  2. Ubuntu安装Skype
  3. 离线GoogleMapAPIV3加载本地谷歌地图并添加标注
  4. 哈工大计组大作业-RISC处理器设计
  5. 【新书推荐】图神经网络导论,清华大学刘知远老师著作
  6. Windows文件夹文件目录自动生成器
  7. 关于团队合作的一些看法
  8. 学生用计算机的按键名称,电脑的各键名称及用途
  9. 《RocketMQ源码分析》NameServer如何处理Broker的连接
  10. 北大青鸟IT教育14%股权挂牌转让