java多线程模拟实现12306售票
2021/4/8 22:25:54
本文主要是介绍java多线程模拟实现12306售票,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
这里写自定义目录标题
业务描述
假设有200张票,用4个线程去订票,不能有两个或者以上的线程订到了
同一个票(原因就不说了),当最后一张票卖掉的时候结束,再订就抛
异常提示出票卖完了。
业务分析,要实现以上功能,
1、需要创建一个车票类,初始化票,卖票的接口
2、自定义异常的一个类。
3、创建卖票线程类,在run方法中卖车票。
*4、初始化车票的线程,负责初始化车票,也就是初始化Ticket类中的数组。
5、创建主方法进行测试。
public class Test { public static void main(String[] args) throws TicketIsEmpty { //创建票仓对象,设置上限为200张车票 Shop myshop = new Shop(200); //创建票仓线程 Thread t1 = new Thread(myshop); //创建售票窗口1 TicketSeller ticketSeller1 = new TicketSeller("张三",myshop); //创建售票窗口2 TicketSeller ticketSeller2 = new TicketSeller("李四",myshop); //创建售票窗口3 TicketSeller ticketSeller3 = new TicketSeller("王五",myshop); //创建售票窗口4 TicketSeller ticketSeller4 = new TicketSeller("赵六",myshop); //等待车票初始化完成后再开始售票 t1.setName("车票初始化线程"); t1.start(); try { t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } //创建售票线程 Thread t2 = new Thread(ticketSeller1); t2.setName("售票窗口1"); Thread t3 = new Thread(ticketSeller2); t3.setName("售票窗口2"); Thread t4 = new Thread(ticketSeller3); t4.setName("售票窗口3"); Thread t5 = new Thread(ticketSeller4); t5.setName("售票窗口4"); //开始售票 t2.start(); t3.start(); t4.start(); t5.start(); } } public class Ticket implements Saleable{ //车票名字 private String name; //车票状态 boolean state; //售票窗口 private TicketSeller ticketSeller; //构造方法 public Ticket(String name, boolean state) { this.name = name; this.state = state; } public String getName() { return name; } public void setName(String name) { this.name = name; } //获取车票状态 public String getState() { return state?"未售出":"已售出"; } //设置车票状态 public void setState(boolean state) { this.state = state; } //线程安全设置,保证不会一票多卖,并且关联售票窗口 public synchronized void saleTicket(TicketSeller ticketSeller){ this.ticketSeller = ticketSeller; //理论来说不会走此分支 if(ticketSeller ==null){ System.out.println("请先设置销售窗口!"); return; } if(state){ //把车票信息改为已售出 this.setState(false); }else{ System.out.println("错误,该车票已售出!"); } } //重写toString()方法 public String toString() { return name + ": " + getState(); } } public class TicketSeller implements Runnable { //售票员名字 private String sellerName; //车票 private Ticket ticket; //票仓 private Shop shop; private int sold = 0; //构造方法 public TicketSeller(String sellerName, Shop shop) { this.sellerName = sellerName; this.shop = shop; } //获取售票员名字 public String getSellerName() { return sellerName; } //设置售票员名字 public void setSellerName(String sellerName) { this.sellerName = sellerName; } //获取售票员销售的车票 public Ticket getTicket() { return ticket; } //设置车票 public void setTicket(Ticket ticket) { this.ticket = ticket; } //获取票仓对象 public Shop getShop() { return shop; } //设置票仓 public void setShop(Shop shop) { this.shop = shop; } @Override public void run() { //判断票仓是否为设置,在构造方法中有设置,理论来说不会走这个分支 if (this.shop == null) { System.out.println("请先设置票仓!"); return; } //执行售票循环,除非接收到票仓生成车票的异常,否则一直循环 while (true) { try { //获取票仓生成的车票 ticket = shop.generateTicket(this); //售出车票 ticket.saleTicket(this); //控制台监控信息 System.out.println(Thread.currentThread().getName() + " 的 " + sellerName + " 售出了 " + ticket.getName()); sold++; } catch (TicketIsEmpty ticketIsEmpty) { System.out.println(Thread.currentThread().getName() + "尝试继续售票,因车票库存已空,售票异常终止。累计售出 " + sold + " 张车票。"); //ticketIsEmpty.printStackTrace(); //刚开始学,我也不知道为什么不加break会死循环, //感觉是和while(true)有关系 break; } } } @Override public String toString() { return sellerName; } } public class Shop implements Runnable { //票仓 private Ticket[] tickets; //售票窗口 private TicketSeller ticketSeller; //车票总数 private int index; //已售出车票数量 private int ticketsold = 0; //剩余车票数量 private int ticketBalance; //构造方法 public Shop(int index) { this.index = index; ticketBalance = index - ticketsold; } public Ticket[] getTickets() { return tickets; } public void setTickets(Ticket[] tickets) { this.tickets = tickets; } public TicketSeller getTicketSeller() { return ticketSeller; } public void setTicketSeller(TicketSeller ticketSeller) { this.ticketSeller = ticketSeller; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public int getTicketsold() { return ticketsold; } public void setTicketsold(int ticketsold) { this.ticketsold = ticketsold; } public int getTicketBalance() { return ticketBalance; } public void setTicketBalance(int ticketBalance) { this.ticketBalance = ticketBalance; } //生成即将出售的车票 public Ticket generateTicket(TicketSeller ticketSeller) throws TicketIsEmpty { //关联售票窗口 this.ticketSeller = ticketSeller; //判断是否存在售票窗口,理论不会走这个分支 if(ticketSeller == null){ System.out.println("请先设置售票窗口!"); System.exit(0); } //如果票还有额度剩余就生成车票 if (ticketBalance > 0) { int ticketNum = ticketsold; //售出车票数量+1 ticketsold++; //车票库存更新 ticketBalance = index - ticketsold; //把生成的车票返回给售票窗口 return tickets[ticketNum]; } else { //如果车票没有库存了,抛出异常 throw new TicketIsEmpty(); } } @Override public void run() { //按照预设的库存上限生成车票库存 tickets = new Ticket[index]; //初始化每张车票的信息,并且全部设置为可出售 for (int i = 0; i < index; i++) { tickets[i] = new Ticket("第 "+(i+1) + " 号车票", true); } System.out.println(Thread.currentThread().getName() + "----->完成,共有 " + index + " 张车票未售出。"); } } //自定义异常类 public class TicketIsEmpty extends Exception{ public TicketIsEmpty() { super(); } public TicketIsEmpty(String message) { super(message); } } //自定义售票接口 public interface Saleable { public void saleTicket(TicketSeller ticketSeller); }
这篇关于java多线程模拟实现12306售票的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南