(将以下所有的java类复制到同一个包下,改包名,找到程序入口就可以运行,或者点击下载链接
https://download.csdn.net/download/h2677lucy/10417661
在最开始学线程的时候完全是懵逼,只知道概念却不理解,不知道什么时候用什么地方用。等到第二次学的时候还是跌跌撞撞,不是能完全理解,所以通过一个小的联系来练习一下。在单机火车票购票系统中,我只用乘客(Passenger)实现Callable接口,在其run方法下实现了订票。最基础的是两个人不能订购同一张火车票。先看一下效果图,然后我来解释。
该系统在没有输入身份证的情况下可以查询始发地和目的地之间的车次(没时间),比如像这样:
在始发地和目的地相同的情况下,它会提示101错误,说始发地和目的地相同。其他情况下会显示两个地点之间的车次。
如果在你没有输入身份证的情况下,点击了订票按钮,他会提示身份证号是NULL
当输入身份证号后,会给你订票,文本域会显示你的订票信息。而且同一个id,只能订购一张火车票。像这样:
在没有界面的情况下,1000个人在1列火车上订购或者票。(一列火车15节车厢,每节100个座位),在下图的示例中没有出现两个乘客订到同一个座位,都依次订座。
java代码
乘客类
package 火车票购票系统;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
public class Passenger implements Callable<String>{
private long id;
private Train hc;
private Map<String,List<Long>> map;
private String key;
private static List<Long> idList = new ArrayList<>();
public Passenger(long id,Train hc) {
// TODO Auto-generated constructor stub
this.id = id;
this.hc = hc;
this.map = hc.map;
//key值 随便选取某一节车厢
}
public String getKey() {
this.key = "第"+(int)(Math.random()*14+1)+"节车厢";
List<Long> list = map.get(key);
for (Long long1 : list) {
if(long1 == 0) {
return this.key;
}
}
return getKey();
}
@Override
public String call() throws Exception {
//判断当前的这个id 是否已经被使用过
for (Long long1 : idList) {
if(long1 == id) {
return "THE ID WAS USED";
}
}
List<Long> list = map.get(getKey());
//获取到某一节车厢的
for (int i = 0; i < list.size(); i++) {
if(list.get(i) == 0) {
//将id添加到idList中防止同一个id购买多个火车票
idList.add(id);
list.set(i, id);
return "\t订单信息\n乘客 :" + id +"\n列车号:"+hc.name+ "\n车厢号:" + key + "\n座位号:" + i;
//控制台打印是的格式
//return "订单信息\t乘客 :" + id +"\t列车号:"+hc.name+ "\t车厢号:" + key + "\t座位号:" + i;
}
}
return null;
}
}
java代码
火车类
package 火车票购票系统;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class Train {
//火车的名称
public String name;
//火车的容量为 mao.size() * list.size()
public Map<String,List<Long>> map;
//火车的 最大节数 为15
private int maxSection = 16;
//每节火车的容量为 100 人
private int maxCapacity = 101;
public Train(String name) {
// TODO Auto-generated constructor stub
this.name = name;
map = new HashMap<String,List<Long>>();
for (int i = 1; i < maxSection; i++) {
List<Long> list = new ArrayList<>();
for (int j = 1; j < maxCapacity; j++) {
list.add((long) 0);
}
map.put("第"+i+"节车厢", list);
}
}
}
java代码
公共基础类
package 火车票购票系统;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComboBox;
import javax.swing.JTextArea;
/**
* 基础公共类 主要实现的功能是
* 初始化 始发地和目的地之间的车次 以及定义子类共同拥有的属性
*
* @author NullChen
*
*/
public class BaseClass {
//定义下拉列表
public JComboBox<String> j1;
public JComboBox<String> j2;
//文本域
public JTextArea jta;
//存储始发地和目的地
public List<String> list1;
public List<String> list2;
//定义开始点 和终点
public int mStart = 0;
public int mEnd = 0;
public BaseClass(JComboBox<String> j1,JComboBox<String> j2,JTextArea jta) {
// TODO Auto-generated constructor stub
this.j1 = j1;
this.j2 = j2;
this.jta = jta;
list1 = new ArrayList<>();
list1.add("西安");
list1.add("宝鸡");
list1.add("洛阳");
list1.add("北京");
list1.add("上海");
list1.add("广州");
list2 = new ArrayList<>(list1);
}
//通过 起始点 和终点来找到车次 返回车次的名字
public String getHcIndex(int mStart,int mEnd) {
class tkOut {
public String[] tkIn = new String[6];
}
tkOut[] tk = new tkOut[6];
// TODO Auto-generated method stub
for (int i = 0; i < 6; i++) {
tk[i] = new tkOut();
for (int j = 0; j < 6; j++) {
tk[i].tkIn[j] = "TK0"+i+"0"+j;
}
}
return tk[mStart].tkIn[mEnd];
}
}
java代码
订票按钮的触发事件
package 火车票购票系统;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import javax.swing.JComboBox;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
* 继承父类BaseClass 实现 监听事件的接口
* 获取位于下拉列表的首项来获取 起始点和终点的int类型的值,然后获取到
* 火车的名字,生成对象
* @author NullChen
*
*/
public class OrderListener extends BaseClass implements ActionListener {
//准备接受身份证号
private JTextField jl;
//乘客对象
private Callable<String> ck;
private static String lastHcName = null;
private Train hc = null;
private static Train lastHc = null;
public OrderListener(JComboBox<String> j1, JComboBox<String> j2, JTextArea jta, JTextField jl) {
// TODO Auto-generated constructor stub
super(j1, j2, jta);
this.jl = jl;
}
@Override
public void actionPerformed(ActionEvent e) {
boolean bj = false;
// TODO 找到起始点和终点
String str1 = (String) j1.getSelectedItem();
String str2 = (String) j2.getSelectedItem();
if (str1.equals(str2)) {
bj = true;
jta.setText("101-ERRO\nTHE START PLACE IS THE END PLACE");
} else {
for (int i = 0; i < list1.size(); i++) {
if (str1.equals(list1.get(i))) {
for (int j = 0; j < list2.size(); j++) {
if (str2.equals(list2.get(j))) {
mStart = i;
mEnd = j;
}
}
}
}
}
try {
// 获取到身份证号码
String id = jl.getText();
// 开始订票
if(mStart != mEnd) {
String hcName = this.getHcIndex(mStart, mEnd);
// 如果上一次的火车和当前的火车是同一个的话 那么就不新生成对象 为了使数据同步 同一个对象内的数据共享。
if (hcName.equals(lastHcName)) {
hc = lastHc;
} else {
hc = new Train(hcName);
lastHc = hc;
lastHcName = hcName;
}
//
// 注释部分为在控制台打印1000个乘客购买同一列车的车票,或者购买不同列车的座位
// Train[] thc = new Train[15];
// for (int i = 0; i < thc.length; i++) {
// thc[i] = new Train("TK00—"+i);
// }
// for (int i = 0; i < 1000; i++) {
// ck = new Passenger(i, thc[1]);
//
// 乘客
ck = new Passenger(Integer.parseInt(id), hc);
FutureTask<String> fck = new FutureTask<>(ck);
Thread tfck = new Thread(fck);
tfck.start();
//获取返回值
String msg = fck.get();
//System.out.println(msg);
jta.setText(msg);
}else {
jta.setText("101-ERRO\nTHE START PLACE IS THE END PLACE");
}
} catch (Exception e1) {
jta.setText("THE USER ID IS NULL");
System.out.println(e1.getMessage());
}
}
}
java代码
查询按钮的触发事件
package 火车票购票系统;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import javax.swing.JComboBox;
import javax.swing.JTextArea;
import sun.font.Font2D;
import sun.font.FontStrike;
import sun.font.FontStrikeDesc;
public class QueryListener extends BaseClass implements ActionListener{
public QueryListener(JComboBox<String> j1,JComboBox<String> j2,JTextArea jta) {
// TODO Auto-generated constructor stub
super(j1, j2, jta);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
int mStart = 0;
int mEnd = 0;
String str1 = (String) j1.getSelectedItem();
String str2 = (String) j2.getSelectedItem();
if(str1.equals(str2)) {
jta.setText("101-ERROR\nTHE START PLACE IS THE END PLACE");
}else {
for (int i = 0; i < list1.size(); i++) {
if(str1.equals(list1.get(i))) {
for (int j = 0; j < list2.size(); j++) {
if(str2.equals(list2.get(j))) {
mStart = i;
mEnd = j;
}
}
}
}
jta.setText(str1+"到"+str2+"的车次有"+getHcIndex(mStart, mEnd));
}
}
}
java代码
程序入口
package 火车票购票系统;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class MainView extends JFrame implements WindowListener{
private JLabel jl,js,jm;
private JComboBox<String> jc,mjc;
private JButton jb,jb2;
private JTextField jf;
private JTextArea jta;
public MainView() {
// TODO Auto-generated constructor stub
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int width = (int)d.getWidth();
int height = (int)d.getHeight();
this.setLayout(null);
this.setBounds(width/3,height/6,600,600);
this.setTitle("12306订票系统");
this.setResizable(false);
//身份证 号 的JLable
jl = new JLabel("身份证号");
jl.setFont(new Font("", Font.BOLD, 20));
jl.setBounds(this.getWidth()/4,this.getHeight()/9,100,30);
//身份证号的 输入框
jf = new JTextField();
jf.setBounds(this.getWidth()/4+100,this.getHeight()/9,200,30);
//始发地
js = new JLabel("始发地");
js.setFont(new Font("", Font.BOLD, 20));
js.setBounds(this.getWidth()/4,this.getHeight()/9+60,100,30);
//始发地的下拉容器
jc = new JComboBox<String>();
jc.addItem("西安");
jc.addItem("宝鸡");
jc.addItem("洛阳");
jc.addItem("北京");
jc.addItem("上海");
jc.addItem("广州");
jc.setFont(new Font("", Font.BOLD, 20));
jc.setBounds(this.getWidth()/4+100,this.getHeight()/9+60,200,30);
//目的地
jm = new JLabel("目的地");
jm.setFont(new Font("", Font.BOLD, 20));
jm.setBounds(this.getWidth()/4,this.getHeight()/9+120,100,30);
//目的地的下拉容器
mjc = new JComboBox<>();
mjc.addItem("西安");
mjc.addItem("宝鸡");
mjc.addItem("洛阳");
mjc.addItem("北京");
mjc.addItem("上海");
mjc.addItem("广州");
mjc.setFont(new Font("", Font.BOLD, 20));
mjc.setBounds(this.getWidth()/4+100,this.getHeight()/9+120,200,30);
//查询车次
jb = new JButton("查询车次");
jb.setFont(new Font("", Font.BOLD, 20));
jb.setBounds(this.getWidth()/4,this.getHeight()/9+180,180,30);
//确认订票
jb2 = new JButton("订票");
jb2.setFont(new Font("", Font.BOLD, 20));
jb2.setBounds(this.getWidth()/4+200,this.getHeight()/9+180,100,30);
//显示订单的区域
jta = new JTextArea();
jta.setLineWrap(true);
jta.setFont(new Font("", Font.BOLD, 20));
jta.setBounds(this.getWidth()/4,this.getHeight()/9+240,300,200);
this.add(jl);
this.add(jf);
this.add(js);
this.add(jc);
this.add(jm);
this.add(mjc);
this.add(jb);
this.add(jb2);
this.add(jta);
jb.addActionListener(new QueryListener(jc, mjc, jta));
jb2.addActionListener(new OrderListener(jc, mjc, jta, jf));
this.addWindowListener(this);
this.setVisible(true);
}
public static void main(String[] args) {
new MainView();
}
@Override
public void windowOpened(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
System.exit(0);
}
@Override
public void windowClosed(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowIconified(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowDeiconified(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowActivated(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowDeactivated(WindowEvent e) {
// TODO Auto-generated method stub
}
}
有错误的地方欢迎批评指正!