多线程---使用synchronized---多窗口出售火车票
2021/12/31 23:43:00
本文主要是介绍多线程---使用synchronized---多窗口出售火车票,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
package com.ldp.demo.Thread; public class Ticket_Synchronized { public static void main(String[] args) { Ticket_tation ticket = new Ticket_tation(); new Thread(ticket, "a") { }.start(); new Thread(ticket, "b") { }.start(); new Thread(ticket, "c") { }.start(); new Thread(ticket, "d") { }.start(); } } class Ticket_tation implements Runnable { private int ticketNum = 10; @Override public void run() { while (ticketNum > 0) { //while和synchronized 的位置不能互换, synchronized (this) { //要不然票会一直是同一个窗口出票 //synchronized 在这里锁的是对象 if (ticketNum==0){ System.out.println( Thread.currentThread().getName()+"出票失败,"+"票已售完!" ); return; } try { Thread.sleep(50);//睡眠50毫秒,要不然执行太快,会是同一个窗口出票 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println((ticketNum--) + "号票已售出!" + Thread.currentThread().getName()); } } } }
结果
10号票已售出!a
9号票已售出!d
8号票已售出!d
7号票已售出!c
6号票已售出!b
5号票已售出!b
4号票已售出!c
3号票已售出!c
2号票已售出!c
1号票已售出!d
a出票失败,票已售完!
c出票失败,票已售完!
b出票失败,票已售完!
这种方式效率太低,因为synchronized(this)锁住的是对象,代码块里所有的内容都被阻塞了,耗费时间,可以改为锁具体操作,即锁扣除票数方法substract_ticket();
package com.ldp.demo.Thread; public class Ticket_Synchronized { public static void main(String[] args) { Ticket_tation ticket = new Ticket_tation(); new Thread(ticket, "a") { }.start(); new Thread(ticket, "b") { }.start(); new Thread(ticket, "c") { }.start(); new Thread(ticket, "d") { }.start(); } } class Ticket_tation implements Runnable { private int ticketNum = 3; public synchronized Result substract_ticket() { if (ticketNum == 0) { return new Result(false, ticketNum); } return new Result(true, ticketNum--); } @Override public void run() { while (ticketNum > 0) { if (ticketNum == 0) { System.out.println(Thread.currentThread().getName() + "出票失败," + "票已售完!"); return; } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } Result result = substract_ticket(); if (!result.isFlag()) { System.out.println(Thread.currentThread().getName() + "出票失败," + "票已售完!"); return; } System.out.println(result.getCount() + "号票已售出!" + Thread.currentThread().getName()); } } } class Result { boolean flag; int count; public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public Result() { } public Result(boolean flag, int count) { this.flag = flag; this.count = count; } }
3号票已售出!a
2号票已售出!d
b出票失败,票已售完!
1号票已售出!c
a出票失败,票已售完!
synchronized锁的是非静态方法也叫对象锁。
多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。(java对象的内存地址是否相同)
synchronized修饰静态的方法也叫类锁
1,要满足方法同步(或者代码块同步)就必须保证多线程访问的是同一个对象(在java内存中的地址是否相同)。
2,类锁和对象锁同时存在时,多线程访问时不会阻塞,因为他们不是一个锁。
假如有两个火车站,每个火车站有两个窗口售票,那就不能锁对象了,要锁具体操作的方法了。
package com.ldp.demo.Thread; import org.apache.commons.lang3.time.StopWatch; /** * 多个火车站多个窗口售票 */ public class ThreadTicket { private static final int NUM = 7; public static int getNum() { return NUM; } public static void main(String[] args) { Ticket.getTicket().setTicketNum(NUM); TicketStation station1 = new TicketStation("南火车站"); TicketStation station2 = new TicketStation("西火车站"); new Thread(station1, "西窗口一").start(); new Thread(station2, "南窗口二").start(); new Thread(station2, "西窗口一").start(); new Thread(station1, "南窗口二").start(); } } class Ticket { private static final Ticket ticket = new Ticket(); public Ticket() { } public static Ticket getTicket() { return ticket; } private int TicketNum; public int getTicketNum() { return TicketNum; } public void setTicketNum(int ticketNum) { this.TicketNum = ticketNum; } public synchronized Result substratTicket() { Result result = new Result(); if (TicketNum == 0) { result.setFlag(false); result.setCount(TicketNum); } else { result.setFlag(true); result.setCount(TicketNum); --TicketNum; } return result; } } class TicketStation implements Runnable { private String name; public String getName() { return name; } public TicketStation() { } public TicketStation(String name) { this.name = name; } @Override public void run() { while (Ticket.getTicket().getTicketNum() > 0) { if (Ticket.getTicket().getTicketNum() == 0) { break; } try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } Result result = Ticket.getTicket().substratTicket(); if (result.isFlag()) { Out.getInstance().write(System.currentTimeMillis(), this, Thread.currentThread().getName(), result.getCount()); } else { System.out.println(System.currentTimeMillis() + this.name + Thread.currentThread().getName() + "出票失败"); } } } } class Result { boolean flag; int count; public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public Result() { } public Result(boolean flag, int count) { this.flag = flag; this.count = count; } }
package com.ldp.demo.Thread; class Out{ private final static Out out=new Out(); private Out(){} public static Out getInstance(){ return out; } static void write(long time,TicketStation station,String adress,int count){ System.out.println(time+ station.getName()+"在"+adress+"卖出了第"+(ThreadTicket.getNum()-count+1)+"票"); } }
这篇关于多线程---使用synchronized---多窗口出售火车票的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-15PingCAP 黄东旭参与 CCF 秀湖会议,共探开源教育未来
- 2024-05-13PingCAP 戴涛:构建面向未来的金融核心系统
- 2024-05-09flutter3.x_macos桌面os实战
- 2024-05-09Rust中的并发性:Sync 和 Send Traits
- 2024-05-08使用Ollama和OpenWebUI在CPU上玩转Meta Llama3-8B
- 2024-05-08完工标准(DoD)与验收条件(AC)究竟有什么不同?
- 2024-05-084万 star 的 NocoDB 在 sealos 上一键起,轻松把数据库编程智能表格
- 2024-05-08Mac 版Stable Diffusion WebUI的安装
- 2024-05-08解锁CodeGeeX智能问答中3项独有的隐藏技能
- 2024-05-08RAG算法优化+新增代码仓库支持,CodeGeeX的@repo功能效果提升