黑马程序员-银行业务调度系统的分析、设计、实现

 

------- android培训java培训、期待与您交流! ----------

业务和需求分析:

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

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

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

3.异步随机生成各种类型的客户,生成类型的客户的比例为:VIP客户:普通客户:快速客户 = 1:6:3

4.客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需的 时间为最小值

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

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

7.随机生成客户时间间隔以及业务办理时间最大值和最小值自定义

8.不实现GUI,只考虑系统逻辑实现,通过Log方式展现程序运行结果

 

面向对象的分析与设计:

* 设计时要遵循一个原则,谁拥有数据,谁就提供操作这些数据的方法

1.一个客户其实就是由银行的取号机生成的一个号码

2.由于客户有三类,每类客户的号码编制都是完全独立的,所以本程序一定要产生三个号码管理器对象,各自管理一类客户的排队号码,这三个号码管理器对象统一由一个取号机来管理,这个取号机对象在整个程序中只能有一个,所以要将其设计为单例

3.各种类型的客户在其对应窗口依次办理业务,准确的说,应该是窗口依次叫号,当一个窗口叫号时,要向对应的号码管理器取号


代码实现:

1.---------------------------------------------------------------------------------------------------

package com.itheima.bank;

 

public class Constants {

// 客户办理业务所需时间最小值, 单位为秒

public static int MIN_SERVICE_TIME = 1;

// 客户办理业务所需时间最大值

public static int MAX_SERVICE_TIME = 10;

// 随机生成普通客户的比例为1

public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;

}

 

2.---------------------------------------------------------------------------------------------------

package com.itheima.bank;

 

public enum CustomerType {

COMMONEXPRESSVIP;

 

public String toString() {

switch (this) {

case COMMON:

return "普通";

case EXPRESS:

return "快速";

case VIP:

return "VIP";

}

return null;

}

}

 

3.---------------------------------------------------------------------------------------------------

package com.itheima.bank;

 

import java.util.ArrayList;

import java.util.List;

/**

 * 号码管理器

 * 

 * @author mrng

 */

public class NumberManager {

// 最后一个被取的号码

private int lastNumber = 1;

// 取完号码后要排队,这个集合就用来模仿队列

private List<Integer> queueNumber = new ArrayList<Integer>();

 

// 客户取号时调用次方法,产生新的号码

public synchronized Integer generateNewNumber() {

// 加入队列

queueNumber.add(lastNumber);

// 将号码返回给调用者

return lastNumber++;

}

 

// 服务窗口叫号时调用这个方法,得到在队列里面的第一个号码

public synchronized Integer fetchServiceNumber() {

if (queueNumber.isEmpty()) {

return null;

}

return queueNumber.remove(0);

}

}


4.---------------------------------------------------------------------------------------------------

package com.itheima.bank;

/**

 * 取号机,只能有一个取号机存在,所以设计为单例

 * 

 * @author mrng

 */

public class NumberMechine {

private NumberManager vipNumberManager = new NumberManager();

private NumberManager commonNumberManager = new NumberManager();

private NumberManager expressNumberManager = new NumberManager();

 

public NumberManager getVipNumberManager() {

return vipNumberManager;

}

 

public NumberManager getCommonNumberManager() {

return commonNumberManager;

}

 

public NumberManager getExpressNumberManager() {

return expressNumberManager;

}

 

private NumberMechine() {

}

 

private static NumberMechine instance = new NumberMechine();

 

// 返回取号机实例

public static NumberMechine getInstance() {

return instance;

}

}


5.---------------------------------------------------------------------------------------------------

package com.itheima.bank;

 

import java.util.Random;

import java.util.concurrent.Executors;

 

/**

 * 服务窗口

 * 

 * @author mrng

 */

public class ServiceWindow {

// 取号机

public static NumberMechine numberMechine = NumberMechine.getInstance();

// 窗口类型,和客户类型一致,默认为普通类型

private CustomerType type = CustomerType.COMMON;

// 窗口编号

private int windowId = 1;

 

public void setType(CustomerType type) {

this.type = type;

}

 

public void setWindowId(int windowId) {

this.windowId = windowId;

}

 

// 使窗口进入可服务状态,开始叫号并服务

public void start() {

Executors.newSingleThreadExecutor().execute(new Runnable() {

public void run() {

while (true) {

Long serviceTime = (new Random()

.nextInt(Constants.MAX_SERVICE_TIME

- Constants.MIN_SERVICE_TIME + 1) + 1) * 1000l;

switch (type) {

case COMMON:

// 叫号

service(numberMechine.getCommonNumberManager(),

serviceTime, CustomerType.COMMON);

break;

case EXPRESS:

boolean flag = service(

numberMechine.getExpressNumberManager(),

Constants.MIN_SERVICE_TIME * 1000l,

CustomerType.EXPRESS);

// 如果没有快速客户,为普通客户服务

if (!flag) {

service(numberMechine.getCommonNumberManager(),

serviceTime, CustomerType.COMMON);

}

break;

case VIP:

boolean flag2 = service(

numberMechine.getVipNumberManager(),

serviceTime, CustomerType.VIP);

// 如果没有VIP客户,为普通客户服务

if (!flag2) {

service(numberMechine.getCommonNumberManager(),

serviceTime, CustomerType.COMMON);

}

break;

}

}

}

});

}

 

private boolean service(NumberManager numberManager, Long serviceTime,

CustomerType customerType) {

// 叫号

Integer number = numberManager.fetchServiceNumber();

System.out.println(windowId + "号" + type + "窗口开始获取" + customerType

"任务");

// 如果没有叫到号,休息一秒

if (number == null) {

// 如果叫的号是普通客户并且没有叫到,说明银行现在没有排队的客户,空闲1秒

if (customerType == CustomerType.COMMON) {

System.out.println(windowId + "号" + type + "窗口没有获取到"

+ customerType + "任务,正在空闲一秒");

try {

Thread.sleep(1000);

catch (InterruptedException e) {

e.printStackTrace();

}

return false;

}

System.out.println(windowId + "号" + type + "窗口没有获取到" + customerType

"任务");

return false;

else {// 如果叫到了号,就开始为客户服务

System.out.println(windowId + "号" + type + "窗口开始为" + number + "号"

+ customerType + "客户服务");

// 开始时间

Long biginTime = System.currentTimeMillis();

try {

Thread.sleep(serviceTime);

catch (InterruptedException e) {

e.printStackTrace();

}

// 本次服务所用的时间

Long costTime = System.currentTimeMillis() - biginTime;

System.out.println(windowId + "号" + type + "窗口为" + number + "号"

+ customerType + "客户服务完成,耗时" + costTime / 1000 + "秒");

return true;

}

}

}

 

    

 

6.---------------------------------------------------------------------------------------------------

package com.itheima.bank;

 

import java.util.concurrent.Executors;

import java.util.concurrent.TimeUnit;

/***

 * 主类

 * 

 * @author mrng

 */

public class MainClass {

public static void main(String[] args) {

// 开启4个普通窗口

for (int i = 1; i <= 4; i++) {

ServiceWindow commonServiceWindow = new ServiceWindow();

commonServiceWindow.setWindowId(i);

commonServiceWindow.start();

}

 

// 开启1个快速窗口

ServiceWindow expressServiceWindow = new ServiceWindow();

expressServiceWindow.setType(CustomerType.EXPRESS);

expressServiceWindow.start();

 

// 开启1个VIP窗口

ServiceWindow vipServiceWindow = new ServiceWindow();

vipServiceWindow.setType(CustomerType.VIP);

vipServiceWindow.start();

 

// 制造普通客户

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

public void run() {

NumberMechine.getInstance().getCommonNumberManager().generateNewNumber();

}

}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME, TimeUnit.SECONDS);

 

// 制造快速客户

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

public void run() {

NumberMechine.getInstance().getExpressNumberManager().generateNewNumber();

}

}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 3, TimeUnit.SECONDS);

 

// 制造vip客户

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

public void run() {

NumberMechine.getInstance().getVipNumberManager().generateNewNumber();

}

}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, TimeUnit.SECONDS);

}

}  

------- android培训java培训、期待与您交流! ----------   
详细请查看:http://edu.csdn.net/heima/ 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值