`
xurichusheng
  • 浏览: 341664 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

【转】 模拟银行业务调度系统

阅读更多

 

转自:CSDN,itm_hadf 的博客 : http://blog.csdn.net/itm_hadf/article/details/7599814

 

注:由于这个程序比较好,所以保存了下来。

 

【一】需求:



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

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

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

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

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

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

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

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

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

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

 

 

【2】面向对象的分析和设计:

        有三种对应类型的客户:VIP客户,普通客户,快速客户 ,异步随机生成各种类型的客户,各类型客户在其对应窗口按顺序依次办理业务 。
         每一个客户其实就是由银行的一个取号机器产生号码的方式来表示的。所以,我想到要有一个号码管理器对象,让这个对象不断地产生号码,就等于随机生成了客户。

         由于有三类客户,每类客户的号码编排都是完全独立的,所以,我想到本系统一共要产生三个号码管理器对象,各自管理一类用户的排队号码。
        这三个号码管理器对象统一由一个号码机器进行管理,这个号码机器在整个系统中始终只能有一个,所以,它要被设计成单例。

         各类型客户在其对应窗口按顺序依次办理业务 ,准确地说,应该是窗口依次叫号。

         各个窗口怎么知道该叫哪一个号了呢?它一定是问的相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码。

具体实现:

 

JDK : 1.6.0_20

 

jar : log4j-1.2.8.jar

       commons-lang-2.4.jar

 

常量类 Constants

/**
 * @ClassName: Constants
 * @Description: 常量类
 * @author 
 * @company 
 * @date 2012-6-13
 * @version V1.0
 */

public class Constants {

	/** 此常量用于表示窗口最大的服务时间 : 10秒 */
	public static final int MAX_SERVICE_TIME = 10000;

	/** 此常量用于表示窗口最小的服务时间 : 1秒 */
	public static final int MIN_SERVICE_TIME = 1000;

	/**
	 * 此常量用于表示为【普通客户】服务的---->> : 间隔时间
	 * 
	 * 每个普通窗口服务一个客户的平均时间为5秒,一共有4个这样的窗口,也就是说银行的所有普通窗口合起来
	 * 平均1.25秒内可以服务完一个普通客户,再加上快速窗口和VIP窗口也可以服务普通客户, 
	 * 所以,1秒钟产生一个普通客户比较合理。。。
	 * 
	 */
	public static final int COMMON_CUSTOMER_INTERVAL_TIME = 1;
}
 

枚举类 CustomerType

/**
 * @ClassName: CustomerType
 * @Description: 系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。
 * @author 
 * @company
 * @date 2012-6-13
 * @version V1.0
 */

public enum CustomerType {

	COMMON, EXPRESS, VIP;

	public String toString() {

		switch (this) {
		case COMMON:
			return "普通客户";
		case EXPRESS:
			return "快速客户";
		case VIP:
			return name();
		}
		return null;
	};
}

 

号码管理器 NumberManager

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

/**
 * @ClassName: NumberManager
 * @Description: 号码管理器.此类用来生成三种 不同类型的号码,以及 对该号码的取得。
 * @author 
 * @company
 * @date 2012-6-13
 * @version V1.0
 */

public class NumberManager {

	private static Logger log = Logger.getLogger(NumberManager.class);

	/** 等待服务队列中的 最后一个号码 */
	private int lastNumber = 1;

	/** 一个等待服务的队列 */
	private BlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>();

	/**
	 * @Title: generateNewManager
	 * @Description: 产生 一个新的号码
	 * @return:Integer
	 * @author 
	 * @date 2012-6-13
	 */
	public Integer generateNewManager() {
		// 将指定元素插入此队列中
		queue.add(lastNumber);

		return lastNumber++;
	}

	/**
	 * @Title: fetchServiceNumber
	 * @Description: 取得一个服务的号码
	 * @return:Integer
	 * @author 
	 * @date 2012-6-13
	 */
	public Integer fetchServiceNumber() {

		Integer number = null;

		if (0 < queue.size()) {

			try {
				/*
				 * 取出BlockingQueue里排在首位的对象,若不能立即取出,则可以等100微妙,
				 * 取不到时返回null
				 */
				number = queue.poll(100, TimeUnit.MICROSECONDS);

			} catch (InterruptedException e) {
				log.error("get the first value of BlockingQueue fail!", e);
			} catch (Exception e) {
				log.error("get the first value of BlockingQueue fail!", e);
			}
		}
		return number;
	}
}
 

号码机器(取号机) NumberMachine

/**
 * @ClassName: NumberMachine
 * @Description: 号码机器(取号机)
 * @author 
 * @company
 * @date 2012-6-13
 * @version V1.0
 */

public class NumberMachine {

	//银行取号机只有一个,故将其设计为单例
	private static final NumberMachine instance = new NumberMachine();
	
	private NumberMachine(){}
	
	public static NumberMachine getInstance() {
		return instance;
	}
	
	/** 普通窗口号码管理器 */
	private NumberManager commonManager = new NumberManager();
	
	/** 快速窗口号码管理器 */
	private NumberManager expressManager = new NumberManager();
	
	/** vip窗口号码管理器  */
	private NumberManager vipManager = new NumberManager();
	

	/**
	 * @return the commonManager(普通窗口号码管理器)
	 */
	public NumberManager getCommonManager() {
		return commonManager;
	}

	/**
	 * @return the expressManager(快速窗口号码管理器)
	 */
	public NumberManager getExpressManager() {
		return expressManager;
	}

	/**
	 * @return the vipManager(vip窗口号码管理器)
	 */
	public NumberManager getVipManager() {
		return vipManager;
	}
}
 

服务窗口 ServiceWindow

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

import org.apache.commons.lang.time.StopWatch;
import org.apache.log4j.Logger;

/**
 * @ClassName: ServiceWindow
 * @Description: 服务窗口(普通窗口,快速窗口,vip窗口)
 * @author 
 * @company 
 * @date 2012-6-13
 * @version V1.0
 */

public class ServiceWindow {

	private static Logger log = Logger.getLogger(ServiceWindow.class);

	/** 客户类型:普通客户 */
	private CustomerType type = CustomerType.COMMON;

	// 服务窗口所显示的号码
	private int windowId = 1;

	/**
	 * @Title: start
	 * @Description: 内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法
	 * @author 
	 * @date 2012-6-13
	 */
	public void start() {

		/** 使用线程池运行 */
		Executors.newSingleThreadExecutor().execute(new Runnable() {

			@Override
			public void run() {

				while (true) {

					switch (type) {
					case COMMON:
						commonService();
						break;
					case EXPRESS:
						expressService();
						break;
					case VIP:
						vipService();
						break;
					}
				}
			}

		});
	}

	/**
	 * @Title: commonService
	 * @Description: 普通客户服务
	 * @author 
	 * @date 2012-6-13
	 */
	private void commonService() {

		String windowName = "第" + windowId + "号" + type + "窗口";

		// 取得一个服务的号码
		Integer serviceNumber = NumberMachine.getInstance().getCommonManager()
				.fetchServiceNumber();

		System.out.println(windowName + "开始获取普通任务!");

		if (null != serviceNumber) {

			System.out.println(windowName + "为第" + serviceNumber + "个普通"
					+ "客户服务");

			StopWatch sWatch = new StopWatch();
			sWatch.start();

			int maxRandom = Constants.MAX_SERVICE_TIME
					- Constants.MIN_SERVICE_TIME;
			// 服务时间
			long serviceTime = new Random().nextInt(maxRandom) + 1
					+ Constants.MIN_SERVICE_TIME;

			try {
				Thread.sleep(serviceTime);
			} catch (InterruptedException e) {
				log.error("Thread sleep InterruptedException", e);
			}

			sWatch.stop();

			System.out.println(windowName + "为第" + serviceNumber + "个" + type
					+ "客户完成服务,耗时:" + sWatch.toString());
		} else {
			System.out.println(windowName + "没有取到任务 ,先休息一秒钟。。。");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				log.error("Thread sleep InterruptedException", e);
			}
		}
	}

	/**
	 * @Title: expressService
	 * @Description: 快速客户服务
	 * @author 
	 * @date 2012-6-13
	 */
	private void expressService() {

		String windowName = "第" + windowId + "号" + type + "窗口";
		// 取得一个服务的号码
		Integer serviceNumber = NumberMachine.getInstance().getExpressManager()
				.fetchServiceNumber();

		System.out.println(windowName + "开始获取快速任务!");

		if (null != serviceNumber) {

			System.out.println(windowName + "为第" + serviceNumber + "个" + type
					+ "客户服务");

			StopWatch sWatch = new StopWatch();
			sWatch.start();

			int serviceTime = Constants.MIN_SERVICE_TIME;
			try {
				/**
				 * 要求 :办理业务的过程----->> : 可以用通过 Sleep 的方式 模拟。
				 * 
				 */
				Thread.sleep(serviceTime);
			} catch (InterruptedException e) {
				log.error("Thread sleep InterruptedException", e);
			}

			sWatch.stop();

			System.out.println(windowName + "为第" + serviceNumber + "个" + type
					+ "客户完成服务,耗时:" + sWatch.toString());
		} else {
			System.out.println(windowName + "没有取到快速任务!");
			/**
			 * 要求 :当 VIP【6】号窗口 和 快速业务【5】号窗口没有客户等待办理业务的时候, 这两个窗口可以处理普通客户的业务。
			 * 而一旦,有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
			 */
			commonService();
		}
	}

	/**
	 * @Title: vipService
	 * @Description: vip客户服务
	 * @author 
	 * @date 2012-6-13
	 */
	private void vipService() {

		String windowName = "第" + windowId + "号" + type + "窗口";
		// 取得一个服务的号码
		Integer serviceNumber = NumberMachine.getInstance().getVipManager()
				.fetchServiceNumber();

		System.out.println(windowName + "开始获取VIP任务!");

		if (null != serviceNumber) {

			System.out.println(windowName + "为第" + serviceNumber + "个" + type
					+ "客户服务");

			StopWatch watch = new StopWatch();
			watch.start();

			int maxRandom = Constants.MAX_SERVICE_TIME
					- Constants.MIN_SERVICE_TIME;
			long serviceTime = new Random().nextInt(maxRandom) + 1
					+ Constants.MIN_SERVICE_TIME;

			try {
				Thread.sleep(serviceTime);
			} catch (InterruptedException e) {
				log.error("Thread sleep InterruptedException", e);
			}

			System.out.println(windowName + "为第" + serviceNumber + "个" + type
					+ "客户服务完成,耗时:" + watch.toString());
		} else {
			System.out.println(windowName + "没有取到VIP任务!");
			commonService();
		}

	}

	/**
	 * @param type
	 *            the type to set
	 */
	public void setType(CustomerType type) {
		this.type = type;
	}

	/**
	 * @param windowId
	 *            the windowId to set
	 */
	public void setWindowId(int windowId) {
		this.windowId = windowId;
	}
}

 

测试 Client

public class Client {

	/**
	 * @Title: main
	 * @Description: TODO
	 * @param args
	 *            :
	 * @author 
	 * @date 2012-6-13
	 */
	public static void main(String[] args) {

		/**
		 * 用for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。 
    	 * 接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码
		 */
		for (int i = 0; i < 5; i++) {
			ServiceWindow commonWindow = new ServiceWindow();
			commonWindow.setWindowId(i);
			commonWindow.start();
		}

		ServiceWindow expressWindow = new ServiceWindow();
		expressWindow.setType(CustomerType.EXPRESS);
		expressWindow.start();

		ServiceWindow vipWindow = new ServiceWindow();
		vipWindow.setType(CustomerType.VIP);
		vipWindow.start();
		
		/**
		 * 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行.
		 * 初始化有1个线程
		 */
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				Integer number = NumberMachine.getInstance().getCommonManager()
						.generateNewManager();
				System.out.println(number + "号普通客户正在等待服务。。。");
			}
		}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME, TimeUnit.SECONDS);

		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				Integer number = NumberMachine.getInstance()
						.getExpressManager().generateNewManager();
				System.out.println(number + "号快速客户正在等待服务。。。");
			}
		}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, TimeUnit.SECONDS);

		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				Integer number = NumberMachine.getInstance().getVipManager()
						.generateNewManager();
				System.out.println(number + "号VIP客户正在等待服务。。。");
			}
		}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2, TimeUnit.SECONDS);
	}

}
 

测试结果:

第0号普通客户窗口开始获取普通任务!
第0号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第1号VIP窗口开始获取VIP任务!
第1号VIP窗口没有取到VIP任务!
第1号VIP窗口开始获取普通任务!
第1号VIP窗口没有取到任务 ,先休息一秒钟。。。
第4号普通客户窗口开始获取普通任务!
第4号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第2号普通客户窗口开始获取普通任务!
第2号普通客户窗口没有取到任务 ,先休息一秒钟。。。
1号快速客户正在等待服务。。。
1号VIP客户正在等待服务。。。
1号普通客户正在等待服务。。。
第1号快速客户窗口开始获取快速任务!
第1号快速客户窗口没有取到快速任务!
第1号普通客户窗口开始获取普通任务!
第1号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第1号快速客户窗口开始获取普通任务!
第1号快速客户窗口为第1个普通客户服务
第3号普通客户窗口开始获取普通任务!
第3号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第0号普通客户窗口开始获取普通任务!
第4号普通客户窗口开始获取普通任务!
第4号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第1号VIP窗口开始获取VIP任务!
第0号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第1号VIP窗口为第1个VIP客户服务
2号普通客户正在等待服务。。。
第2号普通客户窗口开始获取普通任务!
第2号普通客户窗口为第2个普通客户服务
第1号普通客户窗口开始获取普通任务!
第1号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第3号普通客户窗口开始获取普通任务!
第3号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第0号普通客户窗口开始获取普通任务!
第4号普通客户窗口开始获取普通任务!
第4号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第0号普通客户窗口没有取到任务 ,先休息一秒钟。。。
3号普通客户正在等待服务。。。
2号VIP客户正在等待服务。。。
第1号普通客户窗口开始获取普通任务!
第1号普通客户窗口为第3个普通客户服务
第3号普通客户窗口开始获取普通任务!
第3号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第4号普通客户窗口开始获取普通任务!
第0号普通客户窗口开始获取普通任务!
第0号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第4号普通客户窗口没有取到任务 ,先休息一秒钟。。。
4号普通客户正在等待服务。。。
第3号普通客户窗口开始获取普通任务!
第3号普通客户窗口为第4个普通客户服务
第0号普通客户窗口开始获取普通任务!
第0号普通客户窗口没有取到任务 ,先休息一秒钟。。。
第4号普通客户窗口开始获取普通任务!
第4号普通客户窗口没有取到任务 ,先休息一秒钟。。。
5号普通客户正在等待服务。。。
3号VIP客户正在等待服务。。。
第0号普通客户窗口开始获取普通任务!
第0号普通客户窗口为第5个普通客户服务
第4号普通客户窗口开始获取普通任务!
第4号普通客户窗口没有取到任务 ,先休息一秒钟。。。
6号普通客户正在等待服务。。。
第2号普通客户窗口为第2个普通客户客户完成服务,耗时:0:00:04.553
第2号普通客户窗口开始获取普通任务!
第2号普通客户窗口为第6个普通客户服务
第4号普通客户窗口开始获取普通任务!
第4号普通客户窗口没有取到任务 ,先休息一秒钟。。。
7号普通客户正在等待服务。。。
2号快速客户正在等待服务。。。
4号VIP客户正在等待服务。。。
第4号普通客户窗口开始获取普通任务!
第4号普通客户窗口为第7个普通客户服务
8号普通客户正在等待服务。。。

 

分享到:
评论

相关推荐

    银行业务调度系统模拟

    在银行业务调度系统模拟中,我们探讨的核心是一个高效、安全且可靠的系统,它能够处理银行日常的事务操作,包括存款、取款、转账等。这个系统是基于Java编程语言实现的,利用其强大的面向对象特性以及丰富的库支持,...

    软通动力面试题——银行业务调度系统

    系统要求模拟银行业务调度系统的逻辑,包括六个业务窗口,其中一个VIP窗口、一个快速窗口和四个普通窗口。系统需要异步随机生成三种类型的客户:VIP客户、普通客户和快速客户,按照概率比例1:6:3生成客户。每个...

    张孝祥银行业务调度系统笔记

    ### 张孝祥银行业务调度系统笔记:面试题解析与设计思路 银行业务调度系统是银行内部用于管理和调度不同类型的客户及其所办理业务的一种高效机制。本笔记将深入解析题目中提到的银行业务调度系统的设计思路,包括...

    模拟银行调度系统

    **模拟银行调度系统** 在IT领域,开发一个模拟银行调度系统是常见的实践,它能够帮助我们理解和掌握多种关键的技术概念,如Java编程语言中的面向对象编程、多线程处理、单例设计模式以及集合框架的运用。下面我们将...

    利用Java实现的银行业务调度系统

    在本文中,我们将深入探讨如何利用Java编程语言来实现一个银行业务调度系统。这个系统的主要目的是模拟银行窗口的排队和调度机制,以有效地处理多个客户请求。我们将关注以下几个关键知识点: 1. **线程与并发**:...

    银行业务调度系统(做的项目)

    在设计银行业务调度系统时,我们需要关注的主要知识点包括以下几个方面: 1. **面向对象分析与设计**: - **客户类(Customer)**:创建VIP客户、普通客户和快速客户类,每个类包含其特定属性,如客户类型、办理...

    面试题——银行业务调度系统-源代码

    【标题】:“面试题——银行业务调度系统-源代码”涉及的是一个基于JavaSE的银行后台管理系统,旨在处理银行日常的业务调度问题。这个系统可能是为了模拟或优化银行内部的工作流程,例如账户管理、交易处理、客户...

    银行业务调度系统优化版(多线程)

    模拟实现银行业务调度系统逻辑,具体需求如下: 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话...

    基于C++实现的银行业务模拟系统

    4. **银行业务逻辑**:系统应包含模拟银行核心业务的功能,如转账、存款和取款。转账涉及到两个账户之间的操作,需要在事务中完成,确保原子性。存款和取款则涉及单个账户,但也要考虑到账户余额的验证和更新。 5. ...

    银行业务调度视频教学

    《银行业务调度系统视频教程》是一套以JAVA实战为主题的项目教学资源,旨在帮助开发者深入理解如何模拟实现后台银行业务调度。课程由资深讲师张孝祥主讲,通过一系列的视频讲座,逐步解析了从需求分析到系统实现的全...

    java开发的银行调度系统

    模拟实现银行业务调度系统逻辑,具体需求如下: 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话...

    张孝祥 7k面试题 银行业务调度系统改进

    四、服务窗口不用每隔1秒检查,服务完后就检查是否有客户等待服务,而且最好不打印“没取得任务,空闲一秒”,因为作为模拟场景的输出,这样的阅读性不是很好。 五、客户取得号码的时候显示前面有几人在排队字样,...

    基于c/s架构的银行排队调度系统

    3. **银行业务流程模拟**:银行排队调度系统需要模拟真实世界中的银行服务过程,包括客户注册、取号、等待、办理业务以及柜员处理业务等步骤。这需要设计合适的算法来确保公平和高效的排队策略。 4. **多线程技术**...

    银行排队叫号系统实现

    7. **安全性考虑**:由于涉及银行业务,系统必须考虑数据安全和隐私保护,可能采用加密技术保护敏感信息。 8. **测试与调试**:在实际部署前,对系统进行全面的测试,包括单元测试、集成测试和性能测试,确保无bug...

    银行调度系统

    java模拟实现银行业务调度系统逻辑,有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户),异步随机生成各种类型的客户,生成各类型用户的概率比例为:VIP客户 :普通客户 ...

    进程调度模拟系统的设计

    **先来先服务(FCFS)调度算法**是最简单的调度策略,其工作原理如同银行排队等待办理业务:按进程到达的顺序进行服务。FCFS易于实现,但可能导致短进程等待时间过长,长进程优先级过高,影响系统效率。例如,如果一...

    嵌入式课程设计——模拟银行排队叫号系统

    嵌入式课程设计中的模拟银行排队叫号系统是一种在NE-STR750F硬件平台上开发的嵌入式应用,利用IAR Embedded Workbench IDE进行编程。该系统旨在模拟真实的银行服务环境,允许客户取号、排队,并由银行职员通过上位机...

Global site tag (gtag.js) - Google Analytics