Java实现火车票售票系统
一.思路
首先需要一个火车票实体Ticket,用来充当火车票角色;
其次需要一个单例的售票系统TicketSystem,用来售卖火车票;
最后需要具体的售票处Window,用来买票;
二.实现
1.火车票实体Ticket
class Ticket { // 起始站 private String start; // 终点站 private String end; // 票价,用BigDecimal防止后续需要计算,能保证精度 private BigDecimal price; public Ticket() { } public Ticket(String start, String end, BigDecimal price) { this.start = start; this.end = end; this.price = price; } public String getStart() { return start; } public String getEnd() { return end; } public BigDecimal getPrice() { return price; } public void setStart(String start) { this.start = start; } public void setEnd(String end) { this.end = end; } public void setPrice(BigDecimal price) { this.price = price; } @Override public String toString() { return "Ticket{" + "start=" + start + + ", end=" + end + + ", price=" + price + }; } }
2.单例线程安全的售票系统
// 单例系统,双重校验锁 class TicketSystem { private volatile static TicketSystem system = new TicketSystem(); // 存储所有车票,其中CopyOnWriteArrayList保证线程安全读写 private CopyOnWriteArrayList<Ticket> list = new CopyOnWriteArrayList<>(); // 给车票赋值,类加载前就给list车票集合赋值 { for (int i = 0; i < 100; i++) { list.add(new Ticket("北京" + i, "深圳" + i, new BigDecimal(i * 200 + 100))); } } private TicketSystem() { } // 双重锁校验生成系统对象 public static TicketSystem getSystem() { if (system == null) { synchronized (TicketSystem.class) { if (system == null) { system = new TicketSystem(); } } } return system; } // 买票方法 public Ticket sellTicket() { try { return list.remove(0); } catch (IndexOutOfBoundsException e) { // 发生异常说明票卖完了 return null; } } }
3.售票窗口WIndow
// 当前窗口 class Window extends Thread { //当前窗口名称 private String winName; public Window(String winName) { this.winName = winName; } public String getWinName() { return winName; } public void setWinName(String winName) { this.winName = winName; } @Override public void run() { this.sellTicket(); } // 买票系统 public void sellTicket() { TicketSystem system = TicketSystem.getSystem(); while (true) { Ticket ticket = system.sellTicket(); if (ticket != null) { System.out.println("从" + this.winName + "售出一张票" + ticket); } else { System.out.println(this.winName + "票卖光了"); break; } } } }
测试类:
class Test { public static void main(String[] args) { for (int i = 0; i < 3; i++) { Window window = new Window("北京" + i + "站"); window.start(); } } }
总结:运用了双重校验锁的单例模式写售票系统,实现了类的复用,不会被频繁的创建和销毁,节省了时间和空间资源。通过CopyOnWriteArrayList实现线程安全的集合。
拓展:TicketSystem中的票的起始站,票的数量能否自定义呢,更灵活,符合实际场景?