您的位置:首页 > 其它

银行业务调度系统的项目

2015-10-09 19:26 399 查看
这是我第一个博客,这个是从其他网站上找来的资料,并用自己的理解来写的,有很多不对的地方请包涵,最后我会附上 张孝祥-7K月薪面试题破解之二_银行业务调度系统视频教程 原文件。

银行业务调度系统的项目需求

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

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

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

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

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

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

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

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

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

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

分析该需求,java是面向对象,我们需要从该需求中找到相关的对象,然后在从其中找属性和方法。

结合实际,我们可以找到客户类,窗口类,机器类(该类是从实际情况中分析出来的)。

客户类属性:姓名

窗口类属性:窗口编号,窗口姓名。

机器类属性:该机器中有三个管理类,一个是普通号管理类,一个是快速管理类,一个是VIP管理类,管理类中包涵了来的客户的编号,和需要维护的客户队列。

这个分析是慢慢的积累出来的,也有一些课程来,比如UML中类的课程就讲了怎样找类和类的属性、方法。而且找类后在实际编写代码时都有可能在分出类来,这些类是实际需要。

客户类:由于该程序很小,客户类中没有其他的东西,只有一个名字属性,并且不需要客户该对象。这里我们可以创建一个enum,该类中有三个COMMON,FAST,VIP分别表示普通客户,快速客户,vip客户。

public enum Customer {
COMMON, FAST, VIP;
public String toString() {
String name = null;
switch (this) {
case COMMON:
name = "普通";
case FAST:
name = "快速";
case VIP:
name = name();
}
return name;
}
}
该enum中重写了toString()方法,这是用户返回一组汉字。
这样客户类创建好了

窗口类中属性窗口编号,窗口名称
方法:叫号方法
从实际中,我们可以发现银行的窗口叫号,然后客户才来
public class WindonService {
private Customer name = Customer.COMMON;        //窗口名称
private int number = 1;     //窗口编号

/**
* 要完成的任务
*/
public void start(){
//开启线程来完成
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
while(true){
switch (name) {
case COMMON:
commonService();
break;

case FAST:
fastService();
break;

case VIP:
vipService();
break;
}
}
}
});

}

/**
*vip窗口叫号服务
*/
protected void vipService() {
String windonservice = "第" + number + "号" + name + "窗口";
System.out.println(windonservice + ",开始获取vip服务!");
//取号
Integer serviceNumber = NumberMachine.getIntance().getVipManager().fetchNumber();
//判断号码是否为空,如果为空,就等待一段时间
if (serviceNumber != null) {
System.out.println(windonservice+ "正在为第" + serviceNumber+"vip客户服务");
//计算服务时间
//服务时间
int randomTime = Constans.MAX_TIME - Constans.MIN_TIME;
int ServiceTime = new Random().nextInt(randomTime)+1 + Constans.MIN_TIME;
try {
Thread.sleep(ServiceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(windonservice + "为第" + serviceNumber + "vip客户服务" + ServiceTime/1000 +"时间");
}else {
System.out.println("没有取到vip任务,等待一秒钟");
//取到普通号码,则服务普通号码
commonService();
}
}

/**
* 快速窗口叫号服务
*/
protected void fastService() {
String windonservice = "第" + number + "号" + name + "窗口";
System.out.println(windonservice + ",开始获取快速服务!");
//取号
Integer serviceNumber = NumberMachine.getIntance().getFastManager().fetchNumber();
//判断号码是否为空,如果为空,就等待一段时间
if (serviceNumber != null) {
System.out.println(windonservice+ "正在为第" + serviceNumber+"快速客户服务");
//快速服务时间为最小时间
int serviceTime = Constans.MIN_TIME;
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(windonservice + "为第" + serviceNumber + "快速客户服务" + serviceTime/1000 +"时间");
}else {
System.out.println("没有取到快速任务,等待一秒钟");
//快速窗口没有取到快速客户的号码,则试着去取普通号码
//取到普通号码,则服务普通号码
commonService();
}
}

/**
* 普通窗口的服务
*/
protected void commonService() {
String windonservice = "第" + number + "号" + name + "窗口";
System.out.println(windonservice + ",开始获取普通服务!");
//取号
Integer serviceNumber = NumberMachine.getIntance().getCommonManager().fetchNumber();
//判断号码是否为空,如果为空,就等待一段时间
if (serviceNumber != null) {
System.out.println(windonservice+ "正在为第" + serviceNumber+"普通客户服务");
//计算服务时间
//服务时间
int randomTime = Constans.MAX_TIME - Constans.MIN_TIME;
int ServiceTime = new Random().nextInt(randomTime)+1 + Constans.MIN_TIME;
try {
Thread.sleep(ServiceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(windonservice + "为第" + serviceNumber + "普通客户服务" + ServiceTime/1000 +"时间");
}else {
System.out.println("没有取到普通任务,等待一秒钟");
try {
Thread.sleep(1000);         //等待一秒钟
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

// ---------------------------------------------
public Customer getName() {
return name;
}

public void setName(Customer name) {
this.name = name;
}

public int getNumber() {
return number;
}

public void setNumber(int number) {
this.number = number;
}

}


该类中我没有进行优化。所有每个窗口进行叫号,这样,因为有三个窗口,这样我们进行一下区分,进行start()方法,进入start()中后,会进行判断那一个窗口,并进行相应的方法。

普通窗口叫号时,先取出号码,并判断是否有该号码,没有则等待一分钟在叫,有那么就行该客户服务。该客户服务有一个时间,根据需求,需要在最小时间和最大时间之间的随机值。随后就结束服务。

快速窗口叫号时,先取出号码,并判断是否有该号码,没有,这时需要去询问是否有普通客户,此时直接调用普通窗口叫号服务,有那么就行该客户服务。该客户服务有一个时间,根据需求,直接是最小时间。

快速窗口叫号时,先取出号码,并判断是否有该号码,没有,这时需要去询问是否有普通客户,此时直接调用普通窗口叫号服务,有那么就行该客户服务。该客户服务有一个时间,根据需求,需要在最小时间和最大时间之间的随机值。随后就结束服务。

此时该服务类就可以完成。其中会发现如何去得到一个号码呢。该号码是有机器产生的,这时就需要创建机器类,机器类中来创建一个号码管理器,该号码管理器是管理每个到来客户的一个信息的,比如普通客户到时机器到了几号了,同时要维护每次到来客户的队列。该号码管理器能够产生两个方法,取号,产生号码方法。如下:

public class NumberManager {
private Integer lastNumber = 0;
private List<Integer> queueNumber = new ArrayList<Integer>();

/**
* 生成号码
*/
public synchronized Integer generateNumber(){
queueNumber.add(++lastNumber);
return lastNumber;
}
/**
* 取号码
* @return
*/
public synchronized Integer fetchNumber(){
if (queueNumber.size() > 0) {
return queueNumber.remove(0);
}else {
return null;
}
}
}


机器管理类只需维护三个号码管理器就可以了,在实际中机器只有一台,那么该处用到单例,单例的方法如下:

private Class(){}

private static Class mInstance;

public static Class getInstance(){

if(mInstance == null){//Class为类名

mInstance = new Class();

}

return mInstance;

}

机器管理类如下:

public class NumberMachine {
/**
* 由于叫号机器只有一台,必须给其创建单利
* 机器可以生成三种不同号码,普通号码,快速号码,vip号码
*/
private NumberMachine(){}
private static NumberMachine mInstance;

public static NumberMachine getIntance(){
if (mInstance== null) {
mInstance = new NumberMachine();
}
return mInstance;
}

private NumberManager commonManager = new NumberManager();
private NumberManager fastManager = new NumberManager();
private NumberManager vipManager = new NumberManager();

public NumberManager getCommonManager() {
return commonManager;
}
public NumberManager getFastManager() {
return fastManager;
}
public NumberManager getVipManager() {
return vipManager;
}

}


这里有个常量类:

public class Constans {
public static final int MAX_TIME = 10000;           //最大服务时间是10秒
public static final int MIN_TIME = 1000;            //最小服务时间是1秒
}


那么这时完成大部分功能了,有一个功能没有完成,那是怎样随机产生客户,这个会在主方法中完成:

主方法要完成两个功能:

分别创建6个窗口;

按要求产生客户;

按比例产生号码,我想到了使用scheduleAtFixedRate,该方法是周期性的完成任务。其中调用时,有四个参数,一个参数是Runnable,是要完成需要执行的方法,initialDelay 初始延迟时间,period周期,TimeUnit周期的时间单位。

Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {

@Override

public void run() {

}

}, 0, 1, TimeUnit.SECONDS);

这是该方法的调用。

public static void main(String[] args) {
/**
* 创建出6个窗口来
* 然后机器运行起来,生成号码
*/
for (int i = 1; i < 5; i++) {   //创建4个普通窗口
WindonService commonService = new WindonService();
commonService.setName(Customer.FAST);
commonService.start();
}

WindonService fastService = new WindonService();    //创建1个快速窗口
fastService.setName(Customer.VIP);
fastService.start();

WindonService vipService = new WindonService(); //创建1个vip窗口
vipService.setNumber(1);
vipService.start();

Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Integer serviceNumber = NumberMachine.getIntance().getCommonManager().generateNumber();
System.out.println("第" + serviceNumber + "号普通客户正在等待服务!");
}
}, 0, 1, TimeUnit.SECONDS);

Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Integer serviceNumber = NumberMachine.getIntance().getFastManager().generateNumber();
System.out.println("第" + serviceNumber + "号快速客户正在等待服务!");
}
}, 0, 3, TimeUnit.SECONDS);

Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Integer serviceNumber = NumberMachine.getIntance().getVipManager().generateNumber();
System.out.println("第" + serviceNumber + "号vip客户正在等待服务!");
}
}, 0, 6, TimeUnit.SECONDS);
}


总结:

第一结合实际我们要找到有哪几个类,并且确定该类要完成的那个属性和方法。那个接下来的工作就很简单了。

那面我就是找到几个类,最后在主方法中进行创建相关的对象。这里还需要有一些经验的地方是scheduleAtFixedRate,该方法的使用。

大家可以下在下列视屏看

参考:

张孝祥-7K月薪面试题破解之二_银行业务调度系统视频教程
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  博客