银行业务调度系统

来源:互联网 发布:网络创业靠谱吗 编辑:程序博客网 时间:2024/04/30 23:15

银行业务调度系统

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

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

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

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

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

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

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

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

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

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

本程序只是模仿张老师的讲解做出来的,如有不当之处请大神们指出

通过上面的题意可以了解到对象有窗口、客户两个对象对于客户有相对应的编号因此要添加一个编号生成器,窗口通过从编号生成器中取得编号,然后对持有编号的人进行服务,由于用户类型只有三种类型因此用到了枚举类型,本程序要有六个线程分别代表4个普通窗口、一个快速窗口、一个vip窗口具体实现程序如下:

生成客户编号的类:

import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;public class CustomerMachine {    private List<String> commonCustomer=new ArrayList<String>();//装载普通用户    private List<String> fastCustomer=new ArrayList<String>();//装载快速用户    private List<String> vipCustomer=new ArrayList<String>();//装载vip用户    private static int fastNum=1;//对用户个数进行初始化    private static int commonNum=1;    private static int vipNum=1;    public List<String> getCommonCustomer()//取得普通用户的集合    {        return commonCustomer;    }    public List<String> getFastCustomer()//取得快速用户的集合    {        return fastCustomer;    }    public List<String> getVIPCustomer()//取得vip用户的集合    {        return vipCustomer;    }    private CustomerMachine()    {  /*张老师这个地方用了三个线程来完成的,我因为是他去的银行有三台编号的机器,分别编普通的、快速的、还有VIp的但是我觉得只用一台就能实现这个编号功能,而且如    果用一台的话,还省钱,所以我这里就只用一个线程模拟一台机器*/            Executors.newScheduledThreadPool(1).scheduleAtFixedRate(                new Runnable(){                    public void run()                    {                        int flag=(new Random().nextInt(10));//通过随机数来实现1:3:6的结果                        if(flag==0)                        {                            vipCustomer.add("VIP用户_"+(vipNum++)+"号");                        }                        if(flag>0&&flag<4)                            fastCustomer.add("快速用户_"+(fastNum++)+"号");                        if(flag>=4)                            commonCustomer.add("普通用户_"+(commonNum++)+"号");                    }                },                0,                1, //没一秒将会来一个用户                TimeUnit.SECONDS);            }    public static CustomerMachine getInstance()//利用单例设计模式来实现,因为就一个给顾客编码的机器,所以只需创建一次就可以了    {        return cm;    }    private static CustomerMachine cm=new CustomerMachine();}
窗口服务实现类:

import java.util.List;import java.util.Random;import java.util.concurrent.Executors;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class WindowService {private CustomerMachine customer;//代表生成客户编号的对象private int windowNum;//窗口号private WindowType windowType;//窗口类型private static Lock lock=new ReentrantLock();//定义一个锁,因为被多个线程所共用所以表明是静态的public WindowService(CustomerMachine customer,WindowType windowType,int windowNum)//通过构造函数获得客户编号,窗口类型以及窗口号{this.customer=customer;this.windowType=windowType;this.windowNum=windowNum;switch(this.windowType)//选择不同客户然后进行不同的处理{    case COMMON:    Executors.newSingleThreadExecutor().execute(new Runnable(){//创建普通用户的线程    public void run()    {    System.out.println(WindowService.this.windowNum+"号"+WindowService.this.windowType+"等待为你服务");    try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}    while(true)    commonService();    }    });    break;    case FAST:    Executors.newSingleThreadExecutor().execute(new Runnable(){//创建快速用户的线程    public void run()    {    System.out.println(WindowService.this.windowNum+"号"+WindowService.this.windowType+"等待为你服务");    try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}    while(true)    fastService();    }    });    break;    case VIP:    Executors.newSingleThreadExecutor().execute(new Runnable(){//创建vip用户的线程    public void run()    {    System.out.println(WindowService.this.windowNum+"号"+WindowService.this.windowType+"等待为你服务");    try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}    while(true)    vipService();    }    });    break;    }}public void commonService()//处理普通用户的方法{List<String> commonCustomer=customer.getCommonCustomer();if(commonCustomer.size()<=0)//判断是否为空{System.out.println(windowNum+"号"+windowType+"空闲,等待1秒");try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}else{lock.lock();//这个地方加锁,是因为用多个线程在调用普通用户里面的数据,因此要对其加锁,来保证线程的安全性if(commonCustomer.size()<=0){System.out.println(windowNum+"号"+windowType+"空闲,等待1秒");try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}else{System.out.println(windowNum+"号"+windowType+"正在服务"+commonCustomer.get(0));int millis=(new Random().nextInt(5)+1)*1000;//模拟服务时间try {Thread.sleep(millis);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(windowNum+"号"+windowType+"用掉"+millis/1000+"秒服务完"+commonCustomer.remove(0)+"等待新客户服务");}lock.unlock();//将这个锁加载这里面可以提高运行效率,如果要是直接加在第一个if上面那么将会每一次运行都要判断一次锁会降低运行效率                                      //这个就类似在单例模式先的饿汉式中的延迟加载的优化的原理是一致的                          }}public void fastService()//快速用户的处理方法 { List<String> fastCustomer=customer.getFastCustomer(); if(fastCustomer.size()<=0) { commonService(); } else{ System.out.println(windowNum+"号"+windowType+"正在服务"+fastCustomer.get(0)); int millis=1000;//快速窗口的时间最短 try {Thread.sleep(millis);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(windowNum+"号"+windowType+"用掉"+millis/1000+"秒服务完"+fastCustomer.remove(0)+"等待新客户服务");}}public void vipService()//vip用户的处理方法{List<String> vipCustomer=customer.getVIPCustomer();if(vipCustomer.size()<=0){commonService();}else{System.out.println(windowNum+"号"+windowType+"正在服务"+vipCustomer.get(0));//打印正在被服务的客户int millis=(new Random().nextInt(5)+1)*1000;try {Thread.sleep(millis);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(windowNum+"号"+windowType+"用掉"+millis/1000+"秒服务完"+vipCustomer.remove(0)+"等待新客户服务");}}}

通过上面的程序看用到了枚举。下面就是枚举类型:
public enum WindowType {COMMON,FAST,VIP;public String toString()//覆盖父类中的toString方法,在返回的时候按自定义要求打印数据{switch(this){    case COMMON:return "普通窗口";    case FAST:return "快速窗口";    case VIP:return "VIP窗口";}return null;}}
运行整个程序的主类:

public class MainClass {    public static void main(String[] args) {        CustomerMachine customer=CustomerMachine.getInstance();//获得编辑客户编号的对象        for(int i=1;i<=4;i++)//创建普通窗口的四个线程        {            new WindowService(customer, WindowType.COMMON, i);        }        new WindowService(customer, WindowType.FAST, 5);//创建快速窗口的线程        new WindowService(customer, WindowType.VIP, 6);//创建vip窗口的线程    }}
一开始在没有看张老师视频的之前自己现做了一个只分析出一个窗口和客户这两个对象,根本没有考虑到客户编码有一个独立的机器进行处理,虽然基本功能那个倒是显得差不断,但是有点脱离现实,一开始我将客户编号这个功能直接放在了客户类中,然后用窗口类来实现服务功能,最终放在一个主程序中进行运行,这样做毫无扩展性,还有对于每一个ArrayList都用他自身作为对象,没有用它的父类作为他创建的对象引用,通过这个项目让我知道了,面向对象要结合现实来考虑。






原创粉丝点击