java多线程模拟实现12306售票

业务描述

假设有200张票,用4个线程去订票,不能有两个或者以上的线程订到了同一个票(原因就不说了),当最后一张票卖掉的时候结束,再订就抛异常提示出票卖完了。

业务分析

要实现以上功能,1、需要创建一个车票类,初始化票,卖票的接口saleTicket()

2、自定义异常的一个类,这个很简单,不多说。

3、创建卖票线程类,在run方法中卖车票。

4、初始化车票的线程,负责初始化车票,也就是初始化Ticket类中的数组。

5、创建主函数进行测试。

话不多说,上代码。

package javasimple;

public class SaleTicket {

    public static void main(String[] args) {
        // 创建一个初始化线程,若干个买票线程
        // 要等初始化线程初始化好了之后,才能买票

        // 创建一个Ticket类的对象,分别传给不同的线程
        Ticket ticket = new Ticket();

        Thread t1 = new InitTicketThread("初始化线程", ticket);

        // 等初始化线程初始化好车票之后,才能开始卖票
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 创建四个买票线程,开始卖票
        Thread t2 = new SaleTicketThread("卖票线程1", ticket);
        Thread t3 = new SaleTicketThread("卖票线程2", ticket);
        Thread t4 = new SaleTicketThread("卖票线程3", ticket);
        Thread t5 = new SaleTicketThread("卖票线程4", ticket);
    }
}
/**
 * 创建车票类、初始化车票
 * @author haokui
 *
 */
class Ticket {
    // 初始化200张票的空间
    private String[] tickets = new String[200];

    private int index = tickets.length - 1; // 指向数组的索引(第一张票)

    public Ticket() {

    }

    public void initTicket() {
        // 初始化车票,给数组的元素赋值,考虑是否要同步
        for (int i = 0; i < tickets.length; i++) {
            tickets[i] = "第" + (i + 1) + "号车票";
        }
    }

    public synchronized String saleTicket() throws NoTicketException {
        // 判断是否有票,有票的情况下再卖票,没有票呢,抛出异常,
        // 考虑是否需要同步

        if (index >= 0) {
            String s = tickets[index];
            
            // 故意制造了一个问题,出现多个线程共卖一张车票
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            tickets[index] = null;
            index--;
            return s;
        } else {
            throw new NoTicketException("没有车票了");
        }

    }
}
/**
 * 创建卖票线程类
 * @author haokui
 *
 */
class SaleTicketThread extends Thread {

    private Ticket ticket;

    public SaleTicketThread(String name, Ticket ticket) {
        super(name);
        this.ticket = ticket;
        this.start();
    }

    // 在run方法中卖车票
    public void run() {
        for (int i = 0; i < 60; i++) {
            try {
                String s = ticket.saleTicket();
                System.out.println(this.getName() + "卖票成功========>" + s);
            } catch (NoTicketException e) {
                System.out.println(this.getName() + " 卖票时发生异常!");
                e.printStackTrace();
                
                // 如果发生异常,说明没有车票了,就中断循环,不要在卖票了
                break;
            }
        }
    }
}
/**
 * 初始化车票的线程,负责初始化车票,也就是初始化Ticket类中的数组
 * @author haokui
 *
 */
 class InitTicketThread extends Thread {
    private Ticket ticket;
    public InitTicketThread(String name, Ticket ticket) {
        super(name);
        this.ticket = ticket;
        this.start();
    }

    // 在run方法中初始化车票
    public void run() {
        ticket.initTicket();
    }
}
 /**
  * 自定义异常
  * @author haokui
  *
  */
 class NoTicketException extends Exception {
        public NoTicketException() {

        }

        public NoTicketException(String msg) {
            super(msg);
        }
    }

以上代码运行结果如下:

原文地址:https://www.cnblogs.com/hkdpp/p/8418784.html