黑马程序员技术交流社区

标题: 模拟火车票售票系统(多线程运用) [打印本页]

作者: as604049322    时间: 2014-12-23 20:52
标题: 模拟火车票售票系统(多线程运用)
弄了一整天,没弄好,老是在开头出现空指针异常坏了2个售票窗口,望高人指定。我表示多线程好难玩,


  1. import java.util.LinkedList;

  2. class ThreadTest
  3. {
  4.     public static void main(String[] args)
  5.     {
  6.         new ProduceTicketCenter(10000,"产票中心1").start();
  7.         new ProduceTicketCenter(5000,"产票中心2").start();
  8.         new ProduceTicketCenter(7000,"产票中心3").start();
  9.         try{Thread.sleep(100);}catch(Exception e){}
  10.         new SaleTicketWindow("售票窗口1").start();
  11.         new SaleTicketWindow("售票窗口2").start();
  12.         new SaleTicketWindow("售票窗口3").start();
  13.         new SaleTicketWindow("售票窗口4").start();
  14.     }
  15. }

  16. class SaleTicketWindow extends Thread//售票窗口
  17. {
  18.     private static Ticket t=Ticket.getInstanceof();
  19.     private static final int MAX_TICKET=200;//每个售票窗口最多放200张票
  20.     private LinkedList<Integer> tickWin=new LinkedList<Integer>();//当前窗口的票
  21.     boolean flag=true;
  22.     SaleTicketWindow(String name){
  23.         super(name);
  24.     }

  25.     public void run(){
  26.         while(flag){
  27.             sale();
  28.         }
  29.     }
  30.     public synchronized void sale(){
  31.         if(tickWin.size()>0){
  32.             try{Thread.sleep(100);}catch(Exception e){}
  33.             int number=tickWin.removeLast();
  34.             System.out.println(Thread.currentThread().getName()+":编号为"+number+"的票被卖出!信息:");
  35.             System.out.println("姓名:"+creatRandomName());
  36.             String sex=creatRandomSex();
  37.             System.out.println("性别:"+sex);
  38.             System.out.println("身份证号:"+creatRandomIDCard(sex));
  39.             System.out.println("编号:"+Integer.toHexString(number).toUpperCase());
  40.         }else{
  41.             getTickettoWindow();
  42.         }
  43.     }
  44.     public synchronized void getTickettoWindow(){
  45.         while(t.isTickNoNull() && tickWin.size()<MAX_TICKET ){
  46.             tickWin.add(t.getTicket());
  47.         }
  48.     }
  49.     public static String creatRandomSex(){
  50.         if((int)(Math.random()*2)==1)
  51.             return "男";
  52.         else
  53.             return "女";
  54.     }

  55.     public static String creatRandomName(){
  56.         String[] firstName={"王","李","张","刘", "陈","杨","黄","赵", "周","吴","徐","孙", "马","胡","朱","郭", "何","罗","高","林",
  57.                             "郑","梁","谢","唐", "许","冯","宋","韩", "邓","彭","曹","曾", "田","于","肖","潘", "袁","董","叶","杜",
  58.                             "丁","蒋","程","余", "吕","魏","蔡","苏", "任","卢","沈","姜", "姚","钟","崔","陆", "谭","汪","石","付",
  59.                             "贾","范","金","方", "韦","夏","廖","侯", "白","孟","邹","秦", "尹","江","熊","薛", "邱","闫","段","雷",
  60.                             "季","史","陶","毛", "贺","龙","万","顾", "关","郝","孔","向", "龚","邵","钱","武", "扬","黎","汤","戴",
  61.                             "严","文","常","牛", "莫","洪","米","康", "温","代","赖","施"};
  62.         if((int)(Math.random()*2)==0)
  63.             return firstName[(int)(Math.random()*112)]+(char)(Math.random()*10000+21834);
  64.         else
  65.             return firstName[(int)(Math.random()*112)]+(char)(Math.random()*10000+21834)+(char)(Math.random()*10000+21834);
  66.     }
  67. /*
  68. (1)前1、2位数字表示:所在省份的代码;
  69. 身份证号与省份的关系 11 北京市;12 天津市;13 河北省;14 山西省;15 内蒙古自治区;21 辽宁省;22 吉林省;23 黑龙江省;31 上海市;32 江苏省;33 浙江省;
  70. 34 安徽省;35 福建省;36 江西省;37 山东省;41 河南省;42 湖北省;43 湖南省;44 广东省;45 广西壮族自治区;46 海南省;50 重庆市;51 四川省;52 贵州省;
  71. 53 云南省;54 西藏自治区;61 陕西省;62 甘肃省;63 青海省;64 宁夏回族自治区;65 新疆维吾尔自治区;71 台湾省;81 香港特别行政区;82 澳门特别行政区
  72. (2)第3、4位数字表示:所在城市的代码;
  73. (3)第5、6位数字表示:所在区县的代码;
  74. (4)第7~14位数字表示:出生年、月、日;
  75. (5)第15、16位数字表示:所在地的派出所的代码;
  76. (6)第17位数字表示性别:奇数表示男性,偶数表示女性;
  77. 第十八位数字的计算方法为:
  78. 1.将前面的身份证号码17位数分别乘以不同的系数。
  79.   从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
  80. 2.将这17位数字和系数相乘的结果相加。
  81. 3.用加出来和除以11,看余数是多少?
  82. 4.余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。
  83. 其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。
  84.     */
  85.     public static String creatRandomIDCard(String man){
  86.         String IDCard="";
  87.         int[] province={11,12,13,14,15,21,22,23,31,32,33,34,35,36,37,41,42,43,44,45,46,50,51,52,53,54,61,62,63,64,65,71,81,82};
  88.         int temp=province[(int)(Math.random()*province.length)];//省代码
  89.         IDCard+=temp;
  90.         temp=getRandomNum(1,22);//市代码,没搞不清楚,随机生成1~22.
  91.         IDCard+=addNum(temp);
  92.         temp=getRandomNum(1,30);//市代码,没搞不清楚,随机生成1~30.
  93.         IDCard+=addNum(temp);
  94.         temp=getRandomNum(1900,2060);//出生年份为1900~2060年
  95.         IDCard+=temp;
  96.         temp=getRandomNum(1,12);//月份1~12
  97.         IDCard+=addNum(temp);
  98.         temp=getRandomNum(1,30);//日1~30.
  99.         IDCard+=addNum(temp);
  100.         temp=getRandomNum(1,92);//所在地的派出所的代码,没搞不清楚,随机生成1~92.
  101.         IDCard+=addNum(temp);
  102.         if(man=="男")
  103.             temp=((int)(Math.random()*5))<<1+1;
  104.         else
  105.             temp=((int)(Math.random()*5))<<1;
  106.         IDCard+=temp;
  107.         int[] expon=new int[]{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
  108.         String[] checkSheet=new String[]{"1","0","X","9","8","7","6","5","4","3","2"};
  109.         int sum=0;
  110.         for(int i=0;i<expon.length;i++)
  111.             sum+=new Integer(IDCard.charAt(i))*expon[i];
  112.         IDCard+=checkSheet[sum%11];
  113.         return IDCard;
  114.     }
  115.     private static String addNum(int num){
  116.         if(num<10)
  117.             return "0"+num;
  118.         else
  119.             return num+"";
  120.     }
  121.     private static int getRandomNum(int start,int end){
  122.         return (int)(Math.random()*(end-start+1))+start;
  123.     }
  124.     public void changeFlag(){
  125.         flag=!flag;
  126.     }
  127. }

  128. class ProduceTicketCenter extends Thread//产票中心
  129. {
  130.     private static Ticket t=Ticket.getInstanceof();
  131.     boolean flag=true;
  132.     private int max;//代表当前产票中心的产票数量
  133.     private int num=0;//当前产票中心产出的票数
  134.     ProduceTicketCenter(int max,String name){
  135.         super(name);
  136.         this.max=max;
  137.     }
  138.     public void run(){
  139.         while(flag){
  140.             flag=t.ProduceTicket();
  141.             System.out.println(Thread.currentThread().getName()+":产生第"+(++num)+"张票,所有中心总共产生:"+t.getTotal());
  142.             if(num>=max)
  143.                 flag=false;
  144.         }
  145.     }
  146.     public void changeFlag(){
  147.         flag=!flag;
  148.     }
  149. }

  150. class Ticket
  151. {
  152.     private LinkedList<Integer> tickList=new LinkedList<Integer>();
  153.     private int number=700000;//票的起始编号为70万
  154.     private final int MAX=900000;//最大票号为90万
  155.     private static Ticket t=new Ticket();
  156.     private Ticket(){}//单例设计模式
  157.     public static Ticket getInstanceof(){
  158.         return t;
  159.     }
  160.     public synchronized void printList(){
  161.         for(int num:tickList)
  162.         System.out.print(num+",");
  163.     }
  164.     public synchronized boolean ProduceTicket(){
  165.         try{Thread.sleep(20);}catch(Exception e){}
  166.         if(number<=MAX){
  167.                 tickList.add(number++);
  168.             return true;
  169.         }
  170.             return false;
  171.     }
  172.     public int getTicket(){
  173.         return tickList.removeFirst();
  174.     }
  175.     public int getTotal(){
  176.         return number-700000;
  177.     }
  178.     public boolean isTickNoNull(){
  179.         if(tickList.size()>0)
  180.             return true;
  181.         else
  182.             return false;
  183.     }
  184. }
复制代码








欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2