黑馬程序員<銀行業務調度系統>

---------------------- ASP.Net+Unity開發.Net培訓、期待與您交流! ----------------------

1. 銀行業務管理系統

       1. 需求


銀行內有6個業務窗口,1 - 4號窗口爲普通窗口,5號窗口爲快速窗口,6號窗口爲VIP窗口。

有三種對應類型的客戶:VIP客戶,普通客戶,快速客戶(辦理如交水電費、電話費之類業務的客戶)。

異步隨機生成各種類型的客戶,生成各類型用戶的概率比例爲:

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


客戶辦理業務所需時間有最大值和最小值,在該範圍內隨機設定每個VIP客戶以及普通客戶辦理業務所需的時間,快速客戶辦理業務所需時間爲最小值(提示:辦理業務的過程可通過線程Sleep的方式模擬)。

各類型客戶在其對應窗口按順序依次辦理業務。

當VIP(6號)窗口和快速業務(5號)窗口沒有客戶等待辦理業務的時候,這兩個窗口可以處理普通客戶的業務,而一旦有對應的客戶等待辦理業務的時候,則優先處理對應客戶的業務。

隨機生成客戶時間間隔以及業務辦理時間最大值和最小值自定,可以設置。

不要求實現GUI,只考慮系統邏輯實現,可通過Log方式展現程序運行結果。

         2. 面向對象設計

                1. 客戶與號碼的設計

對於不同的客戶,普通,快速客戶,VIP客戶,他們必須首先獲得號碼,來表示本客戶是第幾個客戶,那麼我們就使用集合來存儲,便於操作。

              2. 號碼管理

   我們要使用線程來模擬選號,窗口對客戶的服務,那麼我們就需要線程池 和定時器。

              3.服務窗口

  我們要定義號碼管理類,那麼在銀行中有那麼可以選號機器,並且只有一臺,所以我們要有號碼機器類,用於管理各個類型的號碼管理。現實生活中是窗口中的工作人員通知已經有順序的客戶人員。並且對不同的客戶限制不同的服務時間


      3.編寫

              1.NumberManage

1、定義一個用於存儲上一個客戶號碼的成員變量和用於存儲所有等待服務的客戶號碼的隊列集合。

2、定義一個產生新號碼的方法和獲取馬上要爲之服務的號碼的方法,這兩個方法被不同的線程操作了相同的數據,所以,要進行同步。


import java.util.ArrayList;
import java.util.List;
public class NumberManage {
    private int lastNumber = 1;
    private List<Integer> queueNumber = new ArrayList<Integer>();
    /*抽取號碼*/
    public synchronized Integer generateNewManage() {
        queueNumber.add(lastNumber);
        return lastNumber++;
    }
    /*取出號碼*/
    public synchronized Integer fetchServiceNumber() {
        Integer number = null;
        if (queueNumber.size() > 0)
            number = queueNumber.remove(0);
        return number;
    }
}


2、NumberMachine


定義三個成員變量分別指向三個NumberManager對象,分別表示普通、快速和VIP客戶的號碼管理器,定義三個對應的方法來返回這三個NumberManager對象。

將NumberMachine類設計成單例。

public class NumberMachine {
    private NumberManage commonManage = new NumberManage();
    private NumberManage axpressManage = new NumberManage();
    private NumberManage vipManage = new NumberManage();
    public NumberManage getCommonManage() {
        return commonManage;
    }
    public NumberManage getAxpressManage() {
        return axpressManage;
    }
    public NumberManage getVipManage() {
        return vipManage;
    }
    private static NumberMachine instance = new NumberMachine();
    private NumberMachine() {
    }
    public static NumberMachine getInstance() {
        return instance;
    }
}

3、CustomerType枚舉類


系統中有三種類型的客戶,所以用定義一個枚舉類,其中定義三個成員分別表示三種類型的客戶。

重寫toString方法,返回類型的中文名稱。這是在後面編碼時重構出來的,剛開始不用考慮。

/**
 * 窗口類型枚舉類
 *   1.有普通服務字段
 *   2.快速服務字段
 *   3.VIP服務字段
 *   4.重寫其toString()方法,爲了其輸出清晰,符合我們的習慣
 */
public enum CustomerType {
    COMMON, EXPRESS, VIP;
    public String toString() {
        switch (this) {
        case COMMON:
            return "普通";
        case EXPRESS:
            return "快速";
        case VIP:
            return name();
        }
        return null;
    }
}

4、ServiceWindow


定義一個start方法,內部啓動一個線程,根據服務窗口的類別分別循環調用三個不同的方法。

定義三個方法分別對三種客戶進行服務,爲了觀察運行效果,應詳細打印出其中的細節信息。

import java.util.Random;
import java.util.concurrent.Executors;
import javax.sql.CommonDataSource;
public class ServiceWindow {
    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) {
                    switch (type) {
                    case COMMON:
                        commonService();
                        break;
                    case EXPRESS:
                        expressService();
                        break;
                    case VIP:
                        vipService();
                        break;
                    }
                }
            }
        });
    }
/*普通服務*/
    public void commonService() {
        String windowName = "第" + windowId + "號" + type + "窗口";
                               
        Integer number = NumberMachine.getInstance().getCommonManage()
                .fetchServiceNumber();
        System.out.println(windowName + "開始獲取服務任務");
        if (number != null) {
            System.out.println(windowName + "爲第" + number + "個" + "普通"
                    + "客戶服務");
            long beginTime = System.currentTimeMillis();
            int maxRand = Constants.MAX_SERVICE_TIME
                    - Constants.MIN_SERVICE_TIME;
            long serveTime = new Random().nextInt(maxRand + 1
                    + Constants.MIN_SERVICE_TIME);
            try {
                Thread.sleep(serveTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long closeTime = System.currentTimeMillis() - beginTime;
            System.out.println(windowName + "爲第" + number + "個" + "普通"
                    + "客戶完成服務,耗時:" + (closeTime / 1000) + "秒");
        } else {
            System.out.println(windowName + "沒有取到任務,先休息1秒");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    /*快速服務*/
    public void expressService(){
        String windowName = "第" + windowId + "號" + type + "窗口";
                           
        Integer number = NumberMachine.getInstance().getAxpressManage()
                .fetchServiceNumber();
        System.out.println(windowName + "開始獲取服務任務");
        if (number != null) {
            System.out.println(windowName + "爲第" + number + "個" + type
                    + "客戶服務");
            long beginTime = System.currentTimeMillis();
            try {
                Thread.sleep(Constants.MIN_SERVICE_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long closeTime = System.currentTimeMillis() - beginTime;
            System.out.println(windowName + "爲第" + number + "個" + type
                    + "客戶完成服務,耗時:" + (closeTime / 1000) + "秒");
        } else {
            System.out.println(windowName + "沒有取到任務");
            commonService();
                                   
        }
    }
    /*VIP服務*/
    public void vipService(){
        String windowName = "第" + windowId + "號" + type + "窗口";
                               
        Integer number = NumberMachine.getInstance().getVipManage()
                .fetchServiceNumber();
        System.out.println(windowName + "開始獲取服務任務");
        if (number != null) {
            System.out.println(windowName + "爲第" + number + "個" + type
                    + "客戶服務");
            long beginTime = System.currentTimeMillis();
            int maxRand = Constants.MAX_SERVICE_TIME
                    - Constants.MIN_SERVICE_TIME;
            long serveTime = new Random().nextInt(maxRand + 1
                    + Constants.MIN_SERVICE_TIME);
            try {
                Thread.sleep(serveTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long closeTime = System.currentTimeMillis() - beginTime;
            System.out.println(windowName + "爲第" + number + "個" + type
                    + "客戶完成服務,耗時:" + (closeTime / 1000) + "秒");
        } else {
            System.out.println(windowName + "沒有取到任務");
            commonService();
                                   
        }
    }
}

5、MainClass類與Constants

Constants

定義三個常量:MAX_SERVICE_TIME、MIN_SERVICE_TIME、COMMON_CUSTOMER_INTERVAL_TIME

/**
 *常量字段類
 * 定義服務的最長和最短時間
 *   1.MAX_SERVICE_TIME:最長服務時間
 *   2.MIN_SERVICE_TIM:最短服務時間
 *   3.COMMON_CUSTOMER_INTERVAL_TIME:普通窗口的比例
 */
public class Constants {
   public static int MAX_SERVICE_TIME=10000;
   public static int MIN_SERVICE_TIME=1000;
   public static int COMMON_CUSTOMER_INTERVAL_TIME=1;
}



MainClass

用for循環創建出4個普通窗口,再創建出1個快速窗口和一個VIP窗口。

接着再創建三個定時器,分別定時去創建新的普通客戶號碼、新的快速客戶號碼、新的VIP客戶號碼。


import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
 * 入口類,啓動類
 */
public class MainClass {
    public static void main(String[] args) {
        /**
         * 實例化普通服務窗口
         */
        for(int i=1;i<5;i++){
            ServiceWindow commonWindow=new ServiceWindow();
            commonWindow.setWindowId(i);
        }
        /**
         * 實例化快速服務窗口
         */
        ServiceWindow expressWindow=new ServiceWindow();
        expressWindow.setType(CustomerType.EXPRESS);
        expressWindow.start();
                        
        /**
         * 實例化VIP服務窗口
         */
        ServiceWindow vipWindow=new ServiceWindow();
        vipWindow.setType(CustomerType.VIP);
        vipWindow.start();
                        
        /**
         * 定義了線程定時操作,普通客戶情況。
         */
        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
                new Runnable(){
                    public void run(){
                        Integer number= NumberMachine.getInstance().getCommonManage().generateNewManage();
                        System.out.println(number + "號普通客戶等待服務!");
                    }
                },
                0,
                Constants.COMMON_CUSTOMER_INTERVAL_TIME,
                TimeUnit.SECONDS
                );
                        
                        
        /**
         * 定義了線程定時操作,快速窗口的操作。
         */
                        
        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
                new Runnable(){
                    public void run(){
                        Integer number= NumberMachine.getInstance().getAxpressManage().generateNewManage();
                        System.out.println(number + "號快速客戶等待服務!");
                    }
                },
                0,
                Constants.COMMON_CUSTOMER_INTERVAL_TIME*2,
                TimeUnit.SECONDS
                );
                        
        /**
         * 定義了線程定時操作,VIP客戶情況。
         */
        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
                new Runnable(){
                    public void run(){
                        Integer number= NumberMachine.getInstance().getVipManage().generateNewManage();
                        System.out.println(number + "號VIP等待服務!");
                    }
                },
                0,
                Constants.COMMON_CUSTOMER_INTERVAL_TIME*6,
                TimeUnit.SECONDS
                );
                        
    }
}


--------------------- ASP.Net+Unity開發.Net培訓、期待與您交流! ----------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章