# 题目
设计并实现某火车票售票系统的放票功能:
某车次预留 100 张有座, 在每晚 8 点开启放票功能,每隔 30 分钟随机放出 10 张票。
简单模拟放票、购票功能:显示客户在某时刻抢到某号码的票。
模拟服务器放票,客户端购票功能:服务器显示某时刻放出某些票,在某时刻卖出某张票的信息;客户端显示某时刻买走某张票的信息。
# 思路与代码
服务器为 Producer 类,客户端为 Customer 类,均继承 Thread 实现多线程,然后一个 Tickets 类,表示余票,一个 MyTime 类表示时间(
源代码下载在这儿:cos_javatest2
MyTime 类:passM 函数表示过去 minute 分钟
public class MyTime { | |
int hour; | |
int minute; | |
public MyTime(int hour, int minute) { | |
this.hour = hour%24; | |
this.minute = minute%60; | |
} | |
public synchronized void printTime() { | |
System.out.printf("%02d:%02d ", hour, minute); | |
} | |
public synchronized void passM(int minute) { | |
this.minute += minute; | |
if(this.minute >= 60) { | |
++this.hour; | |
this.minute %= 60; | |
} | |
this.hour %= 24; | |
} | |
@Override | |
public String toString() { | |
return "MyTime{" + | |
"hour=" + hour + | |
", minte=" + minute + | |
'}'; | |
} | |
} |
Tickets 类:
重点,total 为总共预留的票数(100),time 为时间,cid 表示售票编号,已售出 1 票则为 1,pid 为存票编号,存了 10 张则为 10,available 表示是否还有余票,作为同步的标志。初始化均为 0,Tickets 为两个线程所共享的对象
import java.util.List; | |
import java.util.Stack; | |
public class Tickets { | |
int total; // 票总数 | |
MyTime time; // 当前时间 | |
int cid; // 售票序号 | |
int pid; // 存票序号 | |
boolean available; // 是否有余票 | |
public Tickets(int total, MyTime time) { | |
this.total = total; | |
this.time = time; | |
pid = cid = 0; | |
available = false; | |
} | |
public synchronized void passM(int minute) { | |
time.passM(minute); | |
} | |
public synchronized void put(int num) { // 同步方法,实现增加票的功能 | |
if(available) { | |
System.out.println("暂未到存票时间,别急放("); | |
try {wait();} catch (InterruptedException e) {e.printStackTrace();} | |
} | |
pid += num; | |
time.printTime(); | |
System.out.printf("Producer 存票%d张, 当前余票:%d\n", num, pid-cid); | |
available = true; | |
notify(); | |
} | |
public synchronized void sell() { // 同步方法,实现卖出的功能 | |
if(!available) { | |
System.out.printf("暂无余票,别急哦@Customer %d\n", cid); | |
try {wait();} catch (InterruptedException e) {e.printStackTrace();} | |
} | |
time.printTime(); | |
if(available && cid < pid) { | |
System.out.printf("Customer %d 购买了票 %d\n", ++cid, cid); | |
} | |
if(cid == pid) available = false; | |
notify(); | |
} | |
} |
Customer 类如下:继承 Thread,重载 run
假设每 3 分钟有一个顾客买票,与 Producer 类共享 Tickets 对象,所以 Tickets 内部的函数都需是同步的。
public class Custormer extends Thread{ | |
Tickets t = null; | |
Custormer(Tickets t) { | |
this.t = t; | |
} | |
@Override | |
public void run() { | |
System.out.println("Custormer start"); | |
while(t.cid < t.total) { | |
t.sell(); | |
t.passM(3); | |
try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace();} | |
} | |
System.out.println("Custormer ends"); | |
} | |
} |
Producer 类如下:
public class Producer extends Thread { | |
Tickets t = null; | |
Producer(Tickets t) { | |
this.t = t; | |
} | |
@Override | |
public void run() { | |
System.out.println("Producer start"); | |
while(t.pid < t.total) { | |
t.put(10); | |
try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace();} | |
} | |
System.out.println("Producer end"); | |
} | |
} |
主函数:new 两个线程并启动,设置当前时间为 20:00
public class Main { | |
public static void main(String[] args) { | |
System.out.println("mainThread start"); | |
MyTime time = new MyTime(20, 0); | |
time.printTime(); | |
System.out.println(" 当前时间"); | |
Tickets tickets = new Tickets(100, time); | |
Producer pthread = new Producer(tickets); | |
Custormer cthread = new Custormer(tickets); | |
pthread.start(); | |
cthread.start(); | |
System.out.println("mainThread end"); | |
} | |
} |
# 运行结果
运行结果如下图