`

Java实例分析-银行业务调度系统

阅读更多

@version 2010.01.13


→实现思路

(一)有三种对应类型的客户:VIP客户,普通客户,快速客户,异步随机生成各种类型的客户,各类型客户在其对应窗口按顺序依次办理业务。
  1.首先,经常在银行办理业务的人更有利于理解本系统,例如,我经常陪老婆跑银行,对银行的这个业务算是比较熟悉了,我知道每一个客户其实就是由银行的一个取号机器产生号码的方式来表示的。所以,我想到要有一个号码管理器对象,让这个对象不断地产生号码,就等于随机生成了客户。
  2.由于有三类客户,每类客户的号码编排都是完全独立的,所以,我想到本系统一共要产生三个号码管理器对象,各自管理一类用户的排队号码。这三个号码管理器对象统一由一个号码机器进行管理,这个号码机器在整个系统中始终只能有一个,所以,它要被设计成单例
(二)各类型客户在其对应窗口按顺序依次办理业务 ,准确地说,应该是窗口依次叫号。
  1.各个窗口怎么知道该叫哪一个号了呢?它一定是问的相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码
  2.如果我不是多次亲身经历银行的这种业务,再加之积累了大量面向对象的应用开发经验,我也不知道能否轻松进行这种设计,能否发掘出其中隐含的对象信息,我真说不出具体的经验是什么,就是日积月累出来的一种感觉。

 

  →客户(对应号码)

  →一个号码管理器单例、三类客户号码编排独立

  →业务窗口叫号

  →线程同步synchronized

 

类的编码实现

 

(一)NumberManager类
  1.定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。
  2.定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,所以,要进行同步。
源码如下:

package cn.itcast.bankqueue;

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

public class NumberManager {
	private int lastNumber = 0;
	private List queueNumbers = new ArrayList();
	
	public synchronized Integer generateNewNumber(){
		queueNumbers.add(++lastNumber);
		return lastNumber;
	}
	
	public synchronized Integer fetchNumber(){
		if(queueNumbers.size()>0){
			return (Integer)queueNumbers.remove(0);
		}else{
			return null;
		}
	}
}

 
(二)NumberMachine类
  1.定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器,定义三个对应的方法来返回这三个NumberManager对象。
  2.将NumberMachine类设计成单例。
源码如下:

package cn.itcast.bankqueue;

public class NumberMachine {
	
	private NumberMachine(){}
	private static NumberMachine instance = new NumberMachine();
	public static NumberMachine getInstance(){
		return instance;
	}
	
	private NumberManager commonManager = new NumberManager();
	private NumberManager expressManager = new NumberManager();
	private NumberManager vipManager = new NumberManager();
	public NumberManager getCommonManager() {
		return commonManager;
	}
	public NumberManager getExpressManager() {
		return expressManager;
	}
	public NumberManager getVipManager() {
		return vipManager;
	}
}  
 
 

(三)CustomerType枚举类

  1.系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。
  2.重写toString方法,返回类型的中文名称。这是在后面编码时重构出来的。
源码如下:

package cn.itcast.bankqueue;

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;
	}
}

   

(四)ServiceWindow类
  1.定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。
  2.定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。
源码如下:

package cn.itcast.bankqueue;

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

/**
 * 没有把VIP窗口和快速窗口做成子类,是因为实际业务中的普通窗口可以随时被设置为VIP窗口和快速窗口。
 * */
public class ServiceWindow {
	private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");
	private CustomerType type = CustomerType.COMMON;
	private int number = 1;

	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放在case下面
						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 serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber();		
		if(serviceNumber != null ){
			System.out.println(windowName + "开始为第" + serviceNumber + "号普通客户服务");		
			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 + "完成为第" + serviceNumber + "号普通客户服务,总共耗时" + serviceTime/1000 + "秒");		
		}else{
			System.out.println(windowName + "没有取到普通任务,正在空闲一秒");		
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}				
		}
	}
	
	private void expressService(){
		Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchNumber();
		String windowName = "第" + number + "号" + type + "窗口";	
		System.out.println(windowName + "开始获取快速任务!");		
		if(serviceNumber !=null){
			System.out.println(windowName + "开始为第" + serviceNumber + "号快速客户服务");			
			int serviceTime = Constants.MIN_SERVICE_TIME;
			try {
				Thread.sleep(serviceTime);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}		
			System.out.println(windowName + "完成为第" + serviceNumber + "号快速客户服务,总共耗时" + serviceTime/1000 + "秒");		
		}else{
			System.out.println(windowName + "没有取到快速任务!");				
			commonService();
		}
	}
	
	private void vipService(){

		Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchNumber();
		String windowName = "第" + number + "号" + type + "窗口";	
		System.out.println(windowName + "开始获取VIP任务!");			
		if(serviceNumber !=null){
			System.out.println(windowName + "开始为第" + serviceNumber + "号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 + "完成为第" + serviceNumber + "号VIP客户服务,总共耗时" + serviceTime/1000 + "秒");		
		}else{
			System.out.println(windowName + "没有取到VIP任务!");				
			commonService();
		}	
	}
}

 

(五)MainClass类
  1.用for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。
  2.接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。
源码如下:

package cn.itcast.bankqueue;

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

public class MainClass {
	
	private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");

	public static void main(String[] args) {
		//产生4个普通窗口
		for(int i=1;i<5;i++){
			ServiceWindow window =  new ServiceWindow();
			window.setNumber(i);
			window.start();
		}
	
		//产生1个快速窗口
		ServiceWindow expressWindow =  new ServiceWindow();
		expressWindow.setType(CustomerType.EXPRESS);
		expressWindow.start();
		
		//产生1个VIP窗口		
		ServiceWindow vipWindow =  new ServiceWindow();
		vipWindow.setType(CustomerType.VIP);
		vipWindow.start();		
		
		//普通客户拿号
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						Integer serviceNumber = NumberMachine.getInstance().getCommonManager().generateNewNumber();
						/**
						 * 采用logger方式,无法看到直观的运行效果,因为logger.log方法内部并不是直接把内容打印出出来,
						 * 而是交给内部的一个线程去处理,所以,打印出来的结果在时间顺序上看起来很混乱。
						 */
						//logger.info("第" + serviceNumber + "号普通客户正在等待服务!");
						System.out.println("第" + serviceNumber + "号普通客户正在等待服务!");						
					}
				},
				0,
				Constants.COMMON_CUSTOMER_INTERVAL_TIME, 
				TimeUnit.SECONDS);
		
		//快速客户拿号
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						Integer serviceNumber = NumberMachine.getInstance().getExpressManager().generateNewNumber();
						System.out.println("第" + serviceNumber + "号快速客户正在等待服务!");
					}
				},
				0,
				Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2, 
				TimeUnit.SECONDS);
		
		//VIP客户拿号
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						Integer serviceNumber = NumberMachine.getInstance().getVipManager().generateNewNumber();
						System.out.println("第" + serviceNumber + "号VIP客户正在等待服务!");
					}
				},
				0,
				Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, 
				TimeUnit.SECONDS);
	}
}
 
 

(六)Constants类
  1.定义三个常量:MAX_SERVICE_TIME、MIN_SERVICE_TIME、COMMON_CUSTOMER_INTERVAL_TIME。
源码如下:

package cn.itcast.bankqueue;

public class Constants {
	public static int MAX_SERVICE_TIME = 10000; //10秒!
	public static int MIN_SERVICE_TIME = 1000; //1秒!
	
	/*每个普通窗口服务一个客户的平均时间为5秒,一共有4个这样的窗口,也就是说银行的所有普通窗口合起来
	 * 平均1.25秒内可以服务完一个普通客户,再加上快速窗口和VIP窗口也可以服务普通客户,所以,
	 * 1秒钟产生一个普通客户比较合理,*/	
	public static int COMMON_CUSTOMER_INTERVAL_TIME = 1; 	
}
 

 

→要点分析

 

 

 

 

 

分享到:
评论

相关推荐

    JAVA项目:银行业务调度系统视频教程.rar

    银行业务调度系统是Java技术应用的一个典型实例,它涉及到多个关键的技术点和业务流程。 1. **项目背景**:银行业务调度系统通常用于处理银行日常运营中的各种任务,如贷款审批、账户管理、交易处理等。这些任务...

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

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

    模拟银行调度系统

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

    java编写的一个多线程程序,模拟银行排队.zip

    这个名为“BankDemo”的程序就是一个很好的实例,它展示了如何使用Java来模拟一个银行排队系统。在这个系统中,我们可以预想有多个客户(线程)同时等待服务,而银行只有一个服务窗口(线程)。下面我们将深入探讨这...

    java范例开发大全

    实例214 模拟操作系统的进程调度 379 实例215 利用栈将字符串逆序输出 381 实例216 动态的数组链表 382 实例217 你能猜出鱼是谁的宠物吗? 387 实例218 使用Collections类对List的排序操作 393 实例219 LinkedList的...

    JAVA上百实例源码以及开源项目源代码

    Tcp服务端与客户端的JAVA实例源代码 2个目标文件 摘要:Java源码,文件操作,TCP,服务器 Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多...

    java范例开发大全源代码

     实例172 银行自动存取一体机 278  9.4 多态 284  实例173 饮食文化 284  实例174 使用构造方法的重载计算课程的GPA值 287  第10章 内部类与接口(教学视频:41分钟) 290  10.1 成员内部类 290 ...

    Java范例开发大全 (源程序)

     实例214 模拟操作系统的进程调度 379  实例215 利用栈将字符串逆序输出 381  实例216 动态的数组链表 382  实例217 你能猜出鱼是谁的宠物吗? 387  实例218 使用Collections类对List的排序操作 393  ...

    Java范例开发大全(全书源程序)

    实例214 模拟操作系统的进程调度 379 实例215 利用栈将字符串逆序输出 381 实例216 动态的数组链表 382 实例217 你能猜出鱼是谁的宠物吗? 387 实例218 使用Collections类对List的排序操作 393 实例219 ...

    java范例开发大全(pdf&源码)

    实例214 模拟操作系统的进程调度 379 实例215 利用栈将字符串逆序输出 381 实例216 动态的数组链表 382 实例217 你能猜出鱼是谁的宠物吗? 387 实例218 使用Collections类对List的排序操作 393 实例219 LinkedList的...

    一个复杂的用EJB3实现的银行系统

    在这个复杂的银行系统中,EJB3(Enterprise JavaBeans 3.0)被用于构建核心业务逻辑,体现了Java EE平台在企业级应用开发中的强大能力。 【EJB3技术详解】 EJB3是Java EE规范的一部分,它简化了企业级组件的开发,...

    智慧银行大数据可视化展示平台建设和应用总体解决方案.docx

    随着信息技术的发展,银行业务正在经历深刻的变革。传统银行面临着来自互联网金融、金融科技等新兴领域的挑战。为了适应这一变化趋势,提升自身竞争力和服务水平,智慧银行的概念应运而生。大数据作为智慧银行的核心...

    自己写的S2Sh的简易银行系统

    综上所述,这个基于S2Sh的简易银行系统是学习Java Web开发和理解MVC模式的绝佳实例。通过分析和实践,开发者不仅可以掌握S2Sh框架的使用,还能深入了解Web应用的开发流程和设计原则,为进一步提升开发技能奠定基础。

    JavaEE银行柜员业务绩效考核源码数据库sql文档

    此模块涉及日常银行业务的处理,例如存款、取款、转账等。为了保证数据的安全性和准确性,还需要实现事务处理机制来确保每次操作的原子性。 #### 3. 绩效考核模块 此模块主要用于对柜员的工作表现进行评价和记录。...

    VMwareU2VL经营实战

    - **虚拟化**: 将物理资源抽象化为逻辑资源的过程,使得单个硬件可以支持多个独立的操作系统实例。 - **WebLogic**: Oracle公司的一款应用服务器软件,主要用于构建和部署企业级Java应用。 - **Oracle 数据库**: ...

    BM AIX 入门与提高

    - **企业级服务器**:在银行、电信、制造等行业广泛应用于关键业务系统。 - **大数据处理**:支持高性能计算和大规模数据处理任务。 - **云服务**:作为云计算平台的基础操作系统之一。 - **科研计算**:常被用于...

    proguide-draft.pdf

    - **性能分析**: 分析系统性能瓶颈,提高系统效率。 #### 3.5 性能剖析器 - **性能测试**: 对系统进行性能测试,评估程序的执行效率。 - **代码优化**: 根据测试结果进行代码优化。 #### 3.6 文件夹轮询器 - **...

    hmyjsmst.docx

    包括数据处理能力、统计分析能力、业务理解能力和沟通能力等。 **2.5 大数据时代** - **大数据的含义** 大数据指的是无法用传统数据处理应用软件工具进行捕捉、管理和处理的数据集合。 - **产生背景** 随着...

    day-account-ManagementSystem:oop课程项目

    在Java中,这通常是一个包含`main`方法的类,负责加载配置、创建对象实例、调度系统运行等。 总的来说,这个项目提供了一个实践OOP理念的实战平台,通过实现道贤管理系统,学习者可以深入理解Java中的类与对象、...

Global site tag (gtag.js) - Google Analytics