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中的票的起始站,票的数量能否自定义呢,更灵活,符合实际场景?

经验分享 程序员 微信小程序 职场和发展