黑马程序员技术交流社区

标题: 自己写的银行业务调度系统,貌似简单一些。 [打印本页]

作者: zczcyc0201    时间: 2012-10-9 21:29
标题: 自己写的银行业务调度系统,貌似简单一些。
本帖最后由 zczcyc0201 于 2012-10-9 22:01 编辑

看了张老师的教程,理解了思路,自己从头到尾写了一遍。和张老师的有些不一样。
通过写这个还有交通灯那个例子的代码,总结了几条新手容易犯的错误,至少我是犯了,找了半天才找出来。
我写代码的过程中犯的错误有:
1.用一个指向null的对象调用某个方法,可能会导致程序停住,而且没有任何提示。
2.如果想验证一个集合或数组是否为空,不要用if(ArrayList=!null)这样的条件语句,要用ArrayList.size()>0这种条件语句。
3.所有while(true)的代码,不要忘了用单独的线程运行,否则程序会停住。

下面是代码:
package com.zcz.bank;

import java.util.*;
//号码管理器类
public class NumberManager {
        //定义一个集合存放顾客
        private List<Integer> consumers = new ArrayList<Integer>();
        private Integer i = 0;
        
        //生成顾客的方法
        public synchronized Integer generateNumber ()
        {        
                consumers.add(++i);
                //顾客顺序编号增加
                return i;

        }

        //窗口向号码管理器取号的方法
        public synchronized Integer giveNumber()
        {
                if(consumers.size()>0)
                {
                        int removed = consumers.remove(0);
                        return removed;
                }
                else{
                        return null;
                }
        }

}

//取号机类 单例模式
package com.zcz.bank;

public class NumberMachine {
        private NumberManager commonNumberManager = new NumberManager();
        private NumberManager quickNumberManager = new NumberManager();
        private NumberManager VIPNumberManager = new NumberManager();
        
        private NumberMachine(){
               
        }
        private static NumberMachine instance = new NumberMachine();
        public static NumberMachine getInstance(){
                return instance;
        }
        public NumberManager getCommonNumberManager()
        {
                return commonNumberManager;
        }
        public NumberManager getQuickNumberManager()
        {
                return quickNumberManager;
        }
        public  NumberManager getVIPNumberManager()
        {
                return VIPNumberManager;
        }
}

//服务窗口类
package com.zcz.bank;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ServeWindow {
        private ConsumersType type;
        private Integer windowID;
    //让窗口初始化就具备类型和窗口号
    ServeWindow(ConsumersType type,Integer windowID)
    {
            this.type=type;
            this.windowID=windowID;
    }
     //窗口叫号方法
    public void fetchNumber()
    {
    Executors.newSingleThreadExecutor().execute(new Runnable(){
            public void run(){
                while(true)
                {
                        switch(type)
                        {
                        case COMMON:
                                commonServe();
                                break;
                        case QUICK:
                            quickServe();
                            break;
                        case VIP:
                            VipServe();
                            break;
                        }
                }
            }
    });

    }
    public void commonServe()
    {
            System.out.println("第"+windowID+"号"+type+"窗口"+"开始获取普通任务");
            Integer ServeNumber = NumberMachine.getInstance().getCommonNumberManager().giveNumber();
            
            if(ServeNumber != null)
            {
            System.out.println("第"+windowID+"号"+type+"窗口开始为"+"第"+ServeNumber+"普通顾客服务");
            long startTime= System.currentTimeMillis();
            try {
                        Thread.sleep(new Random().nextInt(Constants.DEAL_TASK_MAX_TIME-Constants.DEAL_TASK_MIN_TIME+1)+Constants.DEAL_TASK_MIN_TIME);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
            long costTime = System.currentTimeMillis()-startTime;
            System.out.println("第"+windowID+"号"+type+"窗口为"+"第"+ServeNumber+"号普通顾客服务服务完毕,耗时:"+costTime/1000+"秒!");
            }else{
                    try {
                                Thread.sleep(2000);
                        } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                    System.out.println("暂时没有普通顾客等待");
            }
            
    }
    public void quickServe()
    {
            System.out.println("第"+windowID+"号"+type+"窗口"+"开始获取快速任务");
            Integer ServeNumber = NumberMachine.getInstance().getQuickNumberManager().giveNumber();
            if(ServeNumber != null)
            {
            System.out.println("第"+windowID+"号"+type+"窗口开始为"+"第"+ServeNumber+"快速顾客服务");
            long startTime= System.currentTimeMillis();
            try {
                        Thread.sleep(Constants.DEAL_TASK_MIN_TIME);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
            long costTime = System.currentTimeMillis()-startTime;
            System.out.println("第"+windowID+"号"+type+"窗口为"+"第"+ServeNumber+"号快速顾客服务服务完毕,耗时:"+costTime/1000+"秒!");
            }else{
                    System.out.println("暂时没有快速顾客等待");
                commonServe();
            }
            
    }
    public void VipServe()
    {
            System.out.println("第"+windowID+"号"+type+"窗口"+"开始获取VIP任务");
            Integer ServeNumber = NumberMachine.getInstance().getVIPNumberManager().giveNumber();
            if(ServeNumber != null)
            {
            System.out.println("第"+windowID+"号"+type+"窗口为"+"第"+ServeNumber+"普通顾客服务");
            long startTime= System.currentTimeMillis();
            try {
                        Thread.sleep(new Random().nextInt(Constants.DEAL_TASK_MAX_TIME-Constants.DEAL_TASK_MIN_TIME+1)+Constants.DEAL_TASK_MIN_TIME);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
            long costTime = System.currentTimeMillis()-startTime;
            System.out.println("第"+windowID+"号"+type+"窗口为"+"第"+ServeNumber+"号VIP顾客服务服务完毕,耗时:"+costTime/1000+"秒!");
            }else{
                    System.out.println("暂时没有VIP顾客等待");
                    commonServe();
            }
            
    }
   
}
//常量保存类
package com.zcz.bank;

public class Constants {
   public static final int GENERATE_CONSUMER_MIN_TIME = 1000;
   public static final int GENERATE_CONSUMER_MAX_TIME = 2000;
   public static final int DEAL_TASK_MIN_TIME = 1000;
   public static final int DEAL_TASK_MAX_TIME = 5000;
}
//客户类型枚举类
package com.zcz.bank;

public enum ConsumersType {
  COMMON,QUICK,VIP;
}

//main方法类
package com.zcz.bank;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MainClass {
/**
  * @param args
  */
public static void main(String[] args) {

        new ServeWindow(ConsumersType.COMMON,1).fetchNumber();
        new ServeWindow(ConsumersType.COMMON,2).fetchNumber();
        new ServeWindow(ConsumersType.COMMON,3).fetchNumber();
        new ServeWindow(ConsumersType.COMMON,4).fetchNumber();
        new ServeWindow(ConsumersType.QUICK,5).fetchNumber();
        new ServeWindow(ConsumersType.VIP,6).fetchNumber();
            
        //普通客户拿号
      Executors.newSingleThreadExecutor().execute(new Runnable(){
      public void run()
      {while(true)
      {
       Integer serviceNumber = NumberMachine.getInstance().getCommonNumberManager().generateNumber();
    System.out.println("第" + serviceNumber + "号普通客户正在等待服务!");  
    try {
    Thread.sleep(Constants.GENERATE_CONSUMER_MIN_TIME);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
      }}
      });
               
         
         
        //快速客户拿号
      Executors.newSingleThreadExecutor().execute(new Runnable(){
      public void run()
      {
      while(true)
      {
       Integer serviceNumber = NumberMachine.getInstance().getQuickNumberManager().generateNumber();
    System.out.println("第" + serviceNumber + "号快速客户正在等待服务!");  
    try {
    Thread.sleep(2*Constants.GENERATE_CONSUMER_MIN_TIME);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
      }}
      });
  
  //VIP客户拿号
      Executors.newSingleThreadExecutor().execute(new Runnable(){
      public void run()
      {
      while(true)
      {
       Integer serviceNumber = NumberMachine.getInstance().getVIPNumberManager().generateNumber();
      System.out.println("第" + serviceNumber + "号VIP客户正在等待服务!");  
    try {
    Thread.sleep(6*Constants.GENERATE_CONSUMER_MIN_TIME);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
      }}
      });

}}


作者: 柏占肖    时间: 2012-10-9 21:47
可以把main方法所在的类的代码贴上来吗
作者: zczcyc0201    时间: 2012-10-9 22:02
不好意思 main类忘了贴,张老师用的定时器,我用的while(true)加线程sleep(),效果一样的
作者: 柏占肖    时间: 2012-10-9 23:34
本帖最后由 柏占肖 于 2012-10-9 23:39 编辑

题目中说异步随机生成各类型的客户,生成各类型用户的概率比例为:
VIP客户:普通客户:快速客户=1:6:3
我在你的代码里看到你是把它们定成了1:6:2,还不是概率比例,你做成了数量比例,题目说的是概率,这就可能出现这种情况,就是VIP用户来了很多了,而普通客户却1个都没有来,虽然这种概率很小,但是还是有这种可能性,所以我觉得应该考虑
个人觉得题目这里居然说要异步生成各类型客户,我觉得这不合理,应该是同步的,一般一个银行就一个取号机,而一个取号机是不允许多个人同时操作的,只能是一个人取了号后另一个人再取
以上纯属个人观点,只为交流


呵呵……谢谢你让我知道了remove方法的返回值,以前一直以为他返回的是空,看到你的代码就查了下API
作者: zczcyc0201    时间: 2012-10-10 08:02
因为我看张老师的代码生成客户好像也是固定的比例,老师用的是定时器,要想随机概率,我觉得可以这样写
Integer MAX=GENERATE_CONSUMER_MAX_TIME = 2000;
Integer MIN=GENERATE_CONSUMER_MIN_TIME = 1000;
普通客户生成间隔:
Thread.sleep(new Random().nextInt(MAX-MIN+1)+MIN
快速客户生成间隔:
Thread.sleep(new Random().nextInt(2*(MAX-MIN+1))+2*MIN
VIP客户生成间隔:
Thread.sleep(new Random().nextInt(6*(MAX-MIN+1))+6*MIN

你觉得可以么

作者: 柏占肖    时间: 2012-10-10 08:41
zczcyc0201 发表于 2012-10-10 08:02
因为我看张老师的代码生成客户好像也是固定的比例,老师用的是定时器,要想随机概率,我觉得可以这样写
Int ...

final int TIME = 1000;
普通客户生成间隔:
Thread.sleep(new Random().nextInt(TIME))
快速客户生成间隔:
Thread.sleep(new Random().nextInt(3*TIME)+1)
VIP客户生成间隔:
Thread.sleep(new Random().nextInt(6*TIME)+1)
我觉得这样好点,只要他们产生的概率是1:3:6就行了,没必要在这里还设个产生普通用户的时间的最大值和最小值
这是我写的http://bbs.itheima.com/thread-27530-1-1.html
呵呵……帮我看看我哪些需要改善的,个人觉得取号机做成一个类就行了




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