【黑马程序员】7K面试题之银行调度系统

------- Windows Phone 7手机开发.Net培训、期待与您交流! -------

模拟实现银行业务调度系统逻辑,具体需求如下:

 

Ø        银行内有6个业务窗口,1- 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。

 

Ø        有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。

 

Ø        异步随机生成各种类型的客户,生成各类型用户的概率比例为:

 

        VIP客户 :普通客户 :快速客户 =  1 :6 :3。

 

Ø        客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。

 

Ø        各类型客户在其对应窗口按顺序依次办理业务。

 

Ø        当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。

 

Ø        随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。

 

Ø        不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。

需求分析:

基本逻辑:

客户:来到银行后,先取号。取号后等待窗口喊号。然后到相应窗口办理好业务后离开银行。

窗口:根据顺序喊号,为客户办理好业务后,按照顺序继续喊号。窗口为三种类型,对应窗口为对对应客户服务。

号码产生管理器:客户来到银行后按顺序给客户产生排队号。然后把号码分配给各个窗口。这个号码管理产生器为单例(即只有一个)。即使有多个取号机器,但是多个取号机器操作的是“唯一”的一个号码管理器。


项目所需类:

窗口类:ServiceWindow

窗口有ID、类型等一系列属性;

窗口创建后,开始自动工作。不断查看客户列表是否有客户,有的话为列表第一个客户办理业务,然后稍微休息一下继续为下一位客户办理业务;如果没有客户,也稍微休息一下然后继续看有没有客户到来。

package com.itcast;

import com.itcast.NumberManager;

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

public class ServiceWindow {
	int windowID;//窗口ID
	UserType windowType=null;//窗口类型
	String windowTypeName="";//窗口类型名字
	String userTypeName="";//客户类型名字
	int maxRandom=Constants.MAX_BUSINESS_TIME-Constants.MIN_BUSINESS_TIME;//业务随机时间
	
	
	public ServiceWindow(){}
	public ServiceWindow(int windowID,UserType windowType){
		this.windowID=windowID;
		this.windowType=windowType;
		ExecutorService pool= Executors.newSingleThreadExecutor();
		pool.execute(
				
				new Runnable(){
					public void run(){
						while(true){
							windowTypeName=NumberManager.getInstance().getUserType(ServiceWindow.this.windowType);
							if(NumberManager.getInstance().userNumbeList.size()==0 && NumberManager.getInstance().userExpressNumbeList.size()==0 && NumberManager.getInstance().userVipNumbeList.size()==0){
								System.out.println("当前还没有客户前来办理业务!"+ServiceWindow.this.windowID+"号"+windowTypeName+"窗口状态空闲!");
								
								try {
									Thread.sleep(10000);//休息10秒钟
								} catch (InterruptedException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							}else{
								User user=NumberManager.getInstance().remove(ServiceWindow.this.windowID,ServiceWindow.this.windowType);
								if(user!=null){
									userTypeName=NumberManager.getInstance().getUserType(user.getUserType());
									int businessTime=0;
									try {
										switch (user.getUserType()) {
										case COMMONUSER:
											//普通客户办理业务需要用时,在最大值和最小值之间
											businessTime=new Random().nextInt(ServiceWindow.this.maxRandom)+1+Constants.MIN_BUSINESS_TIME;
											Thread.sleep(businessTime);
											break;
										case EXPRESSUSER:
											//快速客户办理月舞的速度最快
											businessTime=Constants.MIN_BUSINESS_TIME;
											Thread.sleep(businessTime);
											break;
										case VIPUSER:
											//VIP客户办理业务需要用时,在最大值和最小值之间
											businessTime=new Random().nextInt(ServiceWindow.this.maxRandom)+1+Constants.MIN_BUSINESS_TIME;
											Thread.sleep(businessTime);
											break;
										default:
											break;
										}
										System.out.println(user.getNumber()+"号"+userTypeName+"客户在"+ServiceWindow.this.windowID+"号"+windowTypeName+"窗口办理完业务啦!用时:"+businessTime/1000+"."+businessTime%1000+"秒");
										
										System.out.println("业务办理完成休息5秒!");
										Thread.sleep(5000);
										
									} catch (InterruptedException e) {
										// TODO Auto-generated catch block
										e.printStackTrace();
									}
									
								}
								
							}
						}
						
					}
				
				}
				
		);
	}
}
号码产生管理器:

为客户产生排队号码,当窗口索要号码时,把号码给窗口后,删除本号码。每隔一段时间自动产生客户和号码。我这里为了查看系统处理很多各种各样的客户会不会出现bug,设置了每一秒产生一个客户。

package com.itcast;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;





public class NumberManager {
	private static NumberManager numberManager=null;
	
	List<User> userNumbeList=new ArrayList<User>();//普通号码的客户列表
	List<User> userExpressNumbeList=new ArrayList<User>();//快速号码的客户列表
	List<User> userVipNumbeList=new ArrayList<User>();//VIP号码的客户列表
	
	static int number=0;
	static int expressNumber=0;
	static int vipNumber=0;
	public  synchronized void add(User user){
		 userNumbeList.add(user);
	}
	public  synchronized User remove(int windowID,UserType windowType){

		User user=null;
		switch (windowType) {
			case COMMONUSER:
				if(userNumbeList.size()!=0){
					user=userNumbeList.remove(0);
					System.out.println("请"+user.getNumber()+"号普通客户到"+windowID+"号普通窗口办理业务!"+windowID+"号普通窗口开始为"+user.getNumber()+"号普通客户办理业务。");
					System.out.println();
				}
				return user;
			case EXPRESSUSER:
				if(userExpressNumbeList.size()!=0){
					//如果快速客户列表有客户的话执行快速叫号程序
					user=userExpressNumbeList.remove(0);
					System.out.println("请"+user.getNumber()+"号快速客户到"+windowID+"号快速窗口办理业务!"+windowID+"号快速窗口开始为"+user.getNumber()+"号快速客户办理业务。");
					System.out.println();
				}else{
					//如果快速客户列表没有快速客户就查看普通客户列表有没有客户
					if(userNumbeList.size()!=0){
						//如果有就叫号普通客户到快速窗口进行业务操作
						user=userNumbeList.remove(0);
						
						System.out.println("当前"+windowID+"号快速客户窗口无人,请"+user.getNumber()+"号普通客户到"+windowID+"号快速窗口办理业务!"+windowID+"号快速窗口开始为"+user.getNumber()+"号普通客户办理业务。");
						System.out.println();
					}
				}
				return user;
			case VIPUSER:
				if(userVipNumbeList.size()!=0){
					//如果VIP客户列表有客户的话执行VIP叫号程序
					user=userVipNumbeList.remove(0);
						System.out.println("请"+user.getNumber()+"号VIP客户到"+windowID+"号VIP窗口办理业务!"+windowID+"号VIP窗口开始为"+user.getNumber()+"号VIP客户办理业务。");
						System.out.println();
					
				}else{
					//如果VIP客户列表没有快速客户就查看普通客户列表有没有客户
					if(userNumbeList.size()!=0){
						//如果有就叫号普通客户到VIP窗口进行业务操作
						user=userNumbeList.remove(0);
						System.out.println("当前"+windowID+"号VIP客户窗口无人,请"+user.getNumber()+"号普通客户到"+windowID+"号VIP窗口办理业务!"+windowID+"号VIP窗口开始为"+user.getNumber()+"号普通客户办理业务。");
						System.out.println();
					}
				}
				
				
				return user;
	
			default:
				break;
		}
		return user;
		
		
	}
	
	
	private NumberManager(){
		ExecutorService pool= Executors.newSingleThreadExecutor();
		pool.execute(
			new Runnable(){
				public void run(){
					while(true){
						try {
							//(new Random().nextInt(10)+1)*1000
							Thread.sleep(1000);//随机(1-10)秒后产生一个客户
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						int random =new Random().nextInt(10)+1;
						switch (random) {
						case 1:
						case 2:
						case 3:
						case 4:
						case 5:
						case 6:
							number++;
							System.out.println("欢迎第"+number+"位普通客户来到黑马银行!");
							userNumbeList.add(new User(UserType.COMMONUSER,number));
							break;
						case 7:
						case 8:
						case 9:
							expressNumber++;
							System.out.println("欢迎第"+expressNumber+"位快速客户来到黑马银行!");
							userExpressNumbeList.add(new User(UserType.EXPRESSUSER,expressNumber));
							break;
						case 10:
							vipNumber++;
							System.out.println("欢迎第"+vipNumber+"位VIP客户来到黑马银行!");
							userVipNumbeList.add(new User(UserType.VIPUSER,vipNumber));
							break;
						default:
							break;
						}

						
						
					}
				
			}
			}
		);
	}
	
	
	
	public static  NumberManager getInstance(){
		if (numberManager==null){
			//添加锁,使多线程同步更安全
			synchronized(NumberManager.class){
				if (numberManager==null){
					numberManager=new NumberManager();
					
				}
			}
		}
		return numberManager;
	}
	public String getUserType(UserType userType){
		String userTypeName="";
		switch (userType) {
		case COMMONUSER:
			userTypeName="普通";
			return userTypeName;
		case EXPRESSUSER:
			userTypeName="快速";
			return userTypeName;
		case VIPUSER:
			userTypeName="VIP";
			return userTypeName;

		default:
			break;
		}
		return userTypeName;
	}
	
}

窗口为客户办理业务的时间范围Constants:

这是一个配置文件类。以后只需要在这个类中修改时间就能控制办理业务时间范围。

1000等于1秒,最小值不得小于1000;

package com.itcast;

public class Constants {
	//业务所用的时间最大值和最小值
	public static int MAX_BUSINESS_TIME=10000;
	public static int MIN_BUSINESS_TIME=3000;
	
	
}

用户类:User

封装了客户的一些基本信息。便于操作。

package com.itcast;

public class User {
	private String name="王瑞亚";
	private int  number;
	private UserType userType;
	public UserType getUserType() {
		return userType;
	}
	public void setUserType(UserType userType) {
		this.userType = userType;
	}
	public int getNumber() {
		return number;
	}
	public void setNumber(int number) {
		this.number = number;
	}
	
	public String getName() {
		return name;
	}
	User(){}
	User(UserType userType,int  number){
		this.userType=userType;
		this.number=number;
	}
	
}

窗口类型和客户类型枚举类UserType:

package com.itcast;

public enum UserType {
	COMMONUSER,EXPRESSUSER,VIPUSER;
	
}
main方法类,程序开始的地方BankMain:

package com.itcast;

public class BankMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		NumberManager nm=NumberManager.getInstance();
		for(int i=1;i<5;i++){
			//循环创建四个普通窗口
			new ServiceWindow(i,UserType.COMMONUSER);
		}
		
		new ServiceWindow(1,UserType.EXPRESSUSER);//创建一个快速客户窗口
		new ServiceWindow(1,UserType.VIPUSER);//创建一个VIP窗口
	}

}



项目总结:

用了一个晚上思考如果实现逻辑和架构,第二天上午写程序,下午修改bug,我还没有达到张老师一气呵成的功力!还需努力!

这是一个模拟现实中银行业务逻辑的一个小程序,这个项目培养了我对项目需求的分析,以及对项目的构架。一个程序不是功能都完成了就算写完了,还要审视程序的架构,是否是一个健壮的系统,是否易于扩展,是否处理了各种突发情况,程序是否人性化等等。这样才能不断的成长,从运用自己的java技术到合理的运用达到最大好处,这是一个转变。现在我还没有能力拿到一个项目就能马上构架好这个项目的框架。我给自己定了一个职业规划:三年内达到项目经理的水平,当上总监,或创业或当一名老师(由于对张孝祥老师的敬佩,决定跟随他)。

接下来我打算花功夫学习学习软件的设计和数据结构,从而设计完美的代码。

阅尽天下代码,心中自然有码。


下面把控制台输出结果放出来,本人测试很多遍了目前没有发现bug,大家可以复制代码在自己机器运行试试,如果有错误的话请大家联系我在修改。我的QQ1659881336.谢谢啦!

当前还没有客户前来办理业务!1号普通窗口状态空闲!
当前还没有客户前来办理业务!2号普通窗口状态空闲!
当前还没有客户前来办理业务!4号普通窗口状态空闲!
当前还没有客户前来办理业务!3号普通窗口状态空闲!
当前还没有客户前来办理业务!1号快速窗口状态空闲!
当前还没有客户前来办理业务!1号VIP窗口状态空闲!
欢迎第1位普通客户来到黑马银行!
欢迎第2位普通客户来到黑马银行!
欢迎第3位普通客户来到黑马银行!
欢迎第1位快速客户来到黑马银行!
欢迎第4位普通客户来到黑马银行!
欢迎第5位普通客户来到黑马银行!
欢迎第6位普通客户来到黑马银行!
欢迎第1位VIP客户来到黑马银行!
欢迎第7位普通客户来到黑马银行!
欢迎第8位普通客户来到黑马银行!
请1号普通客户到1号普通窗口办理业务!1号普通窗口开始为1号普通客户办理业务。


请2号普通客户到2号普通窗口办理业务!2号普通窗口开始为2号普通客户办理业务。


请3号普通客户到4号普通窗口办理业务!4号普通窗口开始为3号普通客户办理业务。


请4号普通客户到3号普通窗口办理业务!3号普通窗口开始为4号普通客户办理业务。


请1号VIP客户到1号VIP窗口办理业务!1号VIP窗口开始为1号VIP客户办理业务。


请1号快速客户到1号快速窗口办理业务!1号快速窗口开始为1号快速客户办理业务。


欢迎第9位普通客户来到黑马银行!
欢迎第10位普通客户来到黑马银行!
欢迎第2位快速客户来到黑马银行!
1号快速客户在1号快速窗口办理完业务啦!用时:3.0秒
业务办理完成休息5秒!
4号普通客户在3号普通窗口办理完业务啦!用时:3.887秒
业务办理完成休息5秒!
欢迎第3位快速客户来到黑马银行!
3号普通客户在4号普通窗口办理完业务啦!用时:4.80秒
业务办理完成休息5秒!
欢迎第2位VIP客户来到黑马银行!
欢迎第11位普通客户来到黑马银行!
1号普通客户在1号普通窗口办理完业务啦!用时:6.900秒
业务办理完成休息5秒!
欢迎第12位普通客户来到黑马银行!
1号VIP客户在1号VIP窗口办理完业务啦!用时:7.424秒
业务办理完成休息5秒!
欢迎第4位快速客户来到黑马银行!
请2号快速客户到1号快速窗口办理业务!1号快速窗口开始为2号快速客户办理业务。


请5号普通客户到3号普通窗口办理业务!3号普通窗口开始为5号普通客户办理业务。


欢迎第5位快速客户来到黑马银行!
请6号普通客户到4号普通窗口办理业务!4号普通窗口开始为6号普通客户办理业务。


2号普通客户在2号普通窗口办理完业务啦!用时:9.396秒
业务办理完成休息5秒!
欢迎第3位VIP客户来到黑马银行!
欢迎第6位快速客户来到黑马银行!
2号快速客户在1号快速窗口办理完业务啦!用时:3.0秒
业务办理完成休息5秒!
请7号普通客户到1号普通窗口办理业务!1号普通窗口开始为7号普通客户办理业务。


欢迎第7位快速客户来到黑马银行!
请2号VIP客户到1号VIP窗口办理业务!1号VIP窗口开始为2号VIP客户办理业务。


5号普通客户在3号普通窗口办理完业务啦!用时:3.999秒
业务办理完成休息5秒!
欢迎第13位普通客户来到黑马银行!
欢迎第4位VIP客户来到黑马银行!
请8号普通客户到2号普通窗口办理业务!2号普通窗口开始为8号普通客户办理业务。


欢迎第5位VIP客户来到黑马银行!
欢迎第14位普通客户来到黑马银行!
请3号快速客户到1号快速窗口办理业务!1号快速窗口开始为3号快速客户办理业务。


2号VIP客户在1号VIP窗口办理完业务啦!用时:4.398秒
业务办理完成休息5秒!
欢迎第15位普通客户来到黑马银行!
6号普通客户在4号普通窗口办理完业务啦!用时:8.402秒
业务办理完成休息5秒!
请9号普通客户到3号普通窗口办理业务!3号普通窗口开始为9号普通客户办理业务。


欢迎第8位快速客户来到黑马银行!
8号普通客户在2号普通窗口办理完业务啦!用时:3.836秒
业务办理完成休息5秒!
欢迎第16位普通客户来到黑马银行!
3号快速客户在1号快速窗口办理完业务啦!用时:3.0秒
业务办理完成休息5秒!
7号普通客户在1号普通窗口办理完业务啦!用时:7.140秒
业务办理完成休息5秒!
欢迎第17位普通客户来到黑马银行!
欢迎第18位普通客户来到黑马银行!
请3号VIP客户到1号VIP窗口办理业务!1号VIP窗口开始为3号VIP客户办理业务。


欢迎第19位普通客户来到黑马银行!
请10号普通客户到4号普通窗口办理业务!4号普通窗口开始为10号普通客户办理业务。


欢迎第6位VIP客户来到黑马银行!
请11号普通客户到2号普通窗口办理业务!2号普通窗口开始为11号普通客户办理业务。


欢迎第20位普通客户来到黑马银行!
请4号快速客户到1号快速窗口办理业务!1号快速窗口开始为4号快速客户办理业务。


请12号普通客户到1号普通窗口办理业务!1号普通窗口开始为12号普通客户办理业务。








------- Windows Phone 7手机开发.Net培训、期待与您交流! -------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值