黑马程序员技术交流社区

标题: 关于银行业务调度系统 [打印本页]

作者: 贾联国    时间: 2012-5-7 20:47
标题: 关于银行业务调度系统
本帖最后由 贾联国 于 2012-5-7 20:51 编辑

今天真的让我激动不已,当看完了张孝祥老师的视频之后觉得视频里张老师的方法不是很妥当,因为客户都是固定每1秒一个普通客户,每两秒一个快速客户,每6秒一个VIP客户,这种方法过于死板,不能充分体现现实的随机性,也就是说,可能一天都是普通客户,也可能一般的客户都是VIP客户,这可怎么办呢?经过我一下午的努力,终于解决了随机性的问题。这就分享我的代码!       首先我的思路是将客户进入银行的时候目的就很明确,直接从提号机提到自己的身份代号,把提号机和号码管理合为一体,并通过随机来决定客户的身份,随机的比率按照VIP用户:快速用户:普通用户=1:3:6,也就是用随机产生10个数,0为VIP用户,1-3为快速用户,4-9为普通用户,而且把身份代号和用户的编号存到集合中,这就要新建一个Custom(int num ,String level)对象,并写get方法,将Custom存到集合中。具体代码如下:

public class Custom {
private int serviceNumber;
private String level;
public Custom() {
    }
public Custom(int serviceNumber,String level){
  this.serviceNumber=serviceNumber;
  this.level=level;
  
}
public int getServiceNumber() {
        return serviceNumber;
}
public String getLevel() {
        return level;
}
}


import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class NumberManager {
private NumberManager(){}
private static NumberManager instance = new NumberManager();
public static NumberManager getInstance(){
  return instance;
}
private static String level;
public static String getLevel() {
  return level;
}
private  int lastNumber =0;
private  int commenNumber =0;
private  int expressNumber =0;
private  int vipNumber =0;
private List<Custom> queueNumbers = new ArrayList<Custom>();
public synchronized Integer generateNewNumber(){
  int stand =new Random().nextInt(10);
  switch(stand){
  case 4:
  case 5:
  case 6:
  case 7:
  case 8:
  case 9:
   level="普通";
   lastNumber=++commenNumber;
   break;
  case 1:
  case 2:
  case 3:
   level="快速";
   lastNumber=++expressNumber;
   break;
  case 0:
   level="VIP";
   lastNumber=++vipNumber;
   break;
  }
  Custom cus =new Custom(lastNumber,level);
  queueNumbers.add(cus);
  return lastNumber;

}

public synchronized Integer fetchCommenNumber(){
  if(queueNumbers.size()>0){
   for(int i=0;i<queueNumbers.size();i++){
       if(queueNumbers.get(i).getLevel().equals("普通")){
          return  queueNumbers.remove(i).getServiceNumber();
       }
   }
  }
  return null;
}
public synchronized Integer fetchExpressNumber(){
  if(queueNumbers.size()>0){
   for(int i=0;i<queueNumbers.size();i++){
       if(queueNumbers.get(i).getLevel().equals("快速"))
        return  queueNumbers.remove(i).getServiceNumber();
   }
  }
  return null;
}
public synchronized Integer fetchVipNumber(){
  if(queueNumbers.size()>0){
   for(int i=0;i<queueNumbers.size();i++){
       if(queueNumbers.get(i).getLevel().equals("VIP"))
        return  queueNumbers.remove(i).getServiceNumber();
   }
  }
  return null;  
}
}

再利用枚举,创建3个等级对象:VIP,COMMON和EXPRESS,并覆盖toString:

public enum CustomerType {
COMMON,EXPRESS,VIP;
public String toString(){
  String name = null;
  switch(this){
  case COMMON:
   name = "普通";
   break;
  case EXPRESS:
   name = "快速";
   break;
  case VIP:
   name = name();
   break;
  }
  return name;
}
}
接着创建一个常量的类:
public class Constants {
public static int MAX_SERVICE_TIME = 10000;
public static int MIN_SERVICE_TIME = 1000;
public static int COMMON_CUSTOMER_INTERVAL_TIME =1;  
}

接下来便是重头戏,对窗口对象的创建,这里思路和张老师的差不多,但是变量发生了大变化,注意即可:
import java.util.Random;
import java.util.concurrent.Executors;

public class ServiceWindow {
private int number = 1;
private CustomerType type = CustomerType.COMMON;
public CustomerType getType() {
  return type;
}
public void setType(CustomerType type) {
  this.type = type;
}
public void setNumber(int number){
  this.number = number;
}
public void start(){
  Executors.newSingleThreadExecutor().execute(
    new Runnable(){
     public void run(){
      while(true){
       switch(type){
        case COMMON:
         commonService();
         break;
        case EXPRESS:
         expressService();
         break;
        case VIP:
         vipService();
         break;
       }
      }
     }
    });
}


private void commonService() {
  String windowName = "第" + number + "号" + type + "窗口";//这里也没放同步锁,防止死锁  
  System.out.println(windowName + "正在获取任务");
  Integer lastNumber=NumberManager.getInstance().fetchCommenNumber();
  if(lastNumber!=null){
   System.out.println(windowName + "为第"+ lastNumber+ "个普通客户服务");  
   int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
   int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;

   try {
    Thread.sleep(serviceTime);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println(windowName + "为第" + lastNumber + "个普通用户完成任务,耗时" + serviceTime/1000 + "秒");  
  }else{
   System.out.println(windowName + "没取得任务,先休息一会");  
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }   
  }
  
}
private void expressService() {
  String windowName = "第" + number + "号" + type + "窗口";//这里也没放同步锁,防止死锁  
  System.out.println(windowName + "正在获取任务");
  Integer lastNumber=NumberManager.getInstance().fetchExpressNumber();
  if(lastNumber!=null){
   System.out.println(windowName + "为第"+ lastNumber+ "个快速客户服务");  
   int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
   int serviceTime = 1000;

   try {
    Thread.sleep(serviceTime);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println(windowName + "为第" + lastNumber + "个快速用户完成任务,耗时1秒");  
  }else {
   System.out.println(windowName + "没取得任务,受理普通客户");  
   commonService();  
  }
  
}
private void vipService() {
  String windowName = "第" + number + "号" + type + "窗口"; //这里也没放同步锁,防止死锁
  System.out.println(windowName + "正在获取任务");
  Integer lastNumber=NumberManager.getInstance().fetchVipNumber();
  if(lastNumber!=null){
   System.out.println(windowName + "为第"+ lastNumber+ "个VIP客户服务");  
   int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
   int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;

   try {
    Thread.sleep(serviceTime);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println(windowName + "为第" + lastNumber + "个VIP用户完成任务,耗时" + serviceTime/1000 + "秒");  
  }else {
   System.out.println(windowName + "没取得任务,受理普通客户");  
   commonService();  
  }
  
}

}


最后的便是main函数,main函数比老师的要简单的多,因为客户只要一个线程源源不断的产生3种不同的客户就可以了,所以这里客户产生的速度也要加快,权衡值为0.7秒产生一个客户,太快窗口处理不过来,客户太多耗费内存,太慢则窗口闲置太多。

import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MainClass {
public static void main(String[] args) {
  // TODO Auto-generated method stub
  for(int i=1;i<5;i++){
   ServiceWindow window =  new ServiceWindow();
   window.setNumber(i);
   window.start();
  }
  ServiceWindow expressWindow =  new ServiceWindow();
  expressWindow.setType(CustomerType.EXPRESS);
  expressWindow.start();
  
  ServiceWindow vipWindow =  new ServiceWindow();
  vipWindow.setType(CustomerType.VIP);
  vipWindow.start();
  
  Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
    new Runnable(){
     public void run(){
      Integer lastNumber=NumberManager.getInstance().generateNewNumber();
      
      System.out.println(lastNumber+"号"+NumberManager.getLevel()+"客户在等待服务");     
     }
    },
    0,
     Constants.COMMON_CUSTOMER_INTERVAL_TIME*700,
    TimeUnit.MILLISECONDS);
}
}


完工! 这个程序完全可以和张老师的程序一样运行,而且产生的对象随机,更有实际意义。发到这里供大家参考。
进过这个程序的磨练,我觉得编程其实是“痛苦并快乐着”,通过这编程激发了我对java更多的热爱,我一定要通过我的努力进入黑马十期,因为java是我的爱好,还需要其他理由吗?


作者: 王德升    时间: 2012-5-7 21:01
这么长,你自己写的?太不可思议了,祝贺你,




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