业务描述
假设有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); } }
以上代码运行结果如下: