Multi-thread practice (II): Banking Business Scheduling System
I. project requirements:
1. There are 6 business windows in the bank. Window 1-4 is a normal window, window 5 is a quick window, and window 6 is a VIP window.
2. There are three types of customers: VIP customers, ordinary customers, and fast customers (customers who handle services such as water, electricity, and telephone fees ).
3. generate various types of customers at random asynchronously. The probability ratio of each type of user is: VIP Customer: ordinary Customer: fast customer = 1: 6: 3.
4. the maximum and minimum time required for the customer to process the business is set. In this range, the time required for each VIP customer and ordinary customer to process the business is set to the minimum time required for the quick customer to process the business (tip: the business process can be simulated by thread Sleep ).
5. Each type of customer handles the business in sequence in its corresponding window. When the VIP (6) window and quick business (5) window do not have customers waiting for business processing, these two windows can process the business of ordinary customers, once a corresponding customer is waiting for processing the business, the corresponding customer's business is prioritized.
6. randomly generate the customer's time interval and customize the maximum and minimum values of the business processing time. You can set this parameter.
7. You do not need to implement the GUI. You only need to implement the system logic. You can use the Log method to display the program running results.
2. Object-Oriented Analysis
There are three types of customers: VIP customers, General customers, and fast customers. Various types of customers are randomly generated asynchronously, and each type of customers process their businesses in sequence in their corresponding windows. Each customer is represented by a number generator of a bank generating a number. Therefore, I want to have a number manager object, so that this object will generate a number at random.
Because there are three types of customers and each type of customer's number orchestration is completely independent, the system generates three number manager objects, each of which manages the queuing numbers of a class of users. The three phone number manager objects are managed by a single phone number machine. This phone number machine can only have one phone number in the entire system. Therefore, it must be designed as a singleton.
Each type of customer handles the business in sequence in the corresponding window. To be precise, the number of the window should be called in sequence. How do I know which number should I call each window? It must be the corresponding number manager, that is, the number manager in the service window gets the number to be served each time.
Iii. Code Implementation
1. NumberManager:
public class NumberManager {private int newNumber = 0;private List
numList = new ArrayList
();public synchronized Integer generateNewNumber() { numList.add(++newNumber);return newNumber;}public synchronized Integer fetchNumber() {if (numList.size() > 0) {return (Integer) numList.remove(0);} else {return null;}}}
Defines a set of member variables used to store the previous customer number and a queue used to store all customer numbers waiting for service.
Define a method to generate a new number and a method to obtain the number to be served immediately. These two methods are operated on the same data by different threads, So synchronization is required.
2. NumberMachine:
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;}}Define three member variables pointing to three NumberManager objects, indicating the number manager of normal, fast, and VIP customers respectively, and define three corresponding methods to return these three NumberManager objects. Design the NumberMachine class as a singleton.
3. CustomerType:
Public enum CustomerType {COMMON, EXPRESS, VIP; public String toString () {String name = null; switch (this) {case COMMON: name = "COMMON"; break; case EXPRESS: name = "quick"; break; case VIP: name = name (); break;} return name ;}}There are three types of customers in the system. Therefore, an enumeration class is defined. Three members are defined to represent three types of customers.
Override the toString method to return the Chinese name of the type. This is reconstructed in later encoding. You don't need to consider it at the beginning.
4. ServiceWindow:
Public class ServiceWindow {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 () implements executors.newsinglethreadexecutor(cmd.exe cute (new Runnable () {public void run () {while (true) {try {switch (type) {case COMMO N: commonService (); break; case EXPRESS: expressService (); break; case VIP: vipService (); break ;}} catch (Exception e) {e. printStackTrace () ;}}});} private void commonService () throws Exception {String windowName = "" + this. number + "number" + this. type + "window"; System. out. println (windowName + "start to get the common task! "); Integer serviceNumber = NumberMachine. getInstance (). getCommonManager (). fetchNumber (); if (serviceNumber! = Null) {System. out. println (windowName + "Start with" + serviceNumber + "normal customer service"); int maxRandom = Constants. MAX_SERVICE_TIME-Constants. MIN_SERVICE_TIME; int serviceTime = new Random (). nextInt (maxRandom) + 1 + Constants. MIN_SERVICE_TIME; Thread. sleep (serviceTime); System. out. println (windowName + "completed as normal customer service No." + serviceNumber + ", total time consumed" + serviceTime/1000 + "seconds");} else {System. out. println (windowName + "No Get common task, idle for one second "); Thread. sleep (1000) ;}} private void expressService () throws Exception {Integer serviceNumber = NumberMachine. getInstance (). getExpressManager (). fetchNumber (); String windowName = "th" + this. number + "number" + this. type + "window"; System. out. println (windowName + "to get the quick task! "); If (serviceNumber! = Null) {System. out. println (windowName + "Start with" + serviceNumber + "Quick customer service"); int serviceTime = Constants. MIN_SERVICE_TIME; Thread. sleep (serviceTime); System. out. println (windowName + "completed as" + serviceNumber + ", fast customer service, total time consumed" + serviceTime/1000 + "seconds");} else {System. out. println (windowName + "no quick task found! "); CommonService () ;}} private void vipService () throws Exception {Integer serviceNumber = NumberMachine. getInstance (). getVipManager (). fetchNumber (); String windowName = "th" + this. number + "number" + this. type + "window"; System. out. println (windowName + "start to get the VIP task! "); If (serviceNumber! = Null) {System. out. println (windowName + "starting from" + serviceNumber + "VIP Customer Service"); int maxRandom = Constants. MAX_SERVICE_TIME-Constants. MIN_SERVICE_TIME; int serviceTime = new Random (). nextInt (maxRandom) + 1 + Constants. MIN_SERVICE_TIME; Thread. sleep (serviceTime); System. out. println (windowName + "completed as VIP Customer Service No." + serviceNumber + ", total time consumed" + serviceTime/1000 + "seconds");} else {System. out. println (windowName +" No VIP task retrieved! "); CommonService ();}}}Define a start method, start a thread internally, and call three different methods cyclically according to the service window type.
Define three methods to serve three customers respectively. In order to observe the running effect, the detailed information should be printed out in detail.
5. Constants
Public class Constants {public static int MAX_SERVICE_TIME = 10000; // 10 seconds! Public static int MIN_SERVICE_TIME = 1000; // 1 second! Public static int COMMON_CUSTOMER_INTERVAL_TIME = 1 ;}
6. MainClass:
Public class MainClass {public static void main (String [] args) {// generates four common Windows (with four threads enabled) for (int I = 1; I <= 4; I ++) {ServiceWindow commonWindow = new ServiceWindow (); commonWindow. setNumber (I); commonWindow. start () ;}// generate a quick window (start a thread) ServiceWindow expressWindow = new ServiceWindow (); expressWindow. setType (CustomerType. EXPRESS); expressWindow. start (); // generate one VIP window (start a thread) ServiceWindow vipWindow = new Servi CeWindow (); vipWindow. setType (CustomerType. VIP); vipWindow. start (); // every second, an ordinary customer takes the number (enable the timer) Executors. newScheduledThreadPool (1 ). scheduleAtFixedRate (new Runnable () {public void run () {Integer serviceNumber = NumberMachine. getInstance (). getCommonManager (). generateNewNumber (); System. out. println ("no." + serviceNumber + "normal customers are waiting for service! ") ;}}, 0, Constants. COMMON_CUSTOMER_INTERVAL_TIME, TimeUnit. SECONDS); // every two SECONDS, a quick customer takes the number (enable the timer) Executors. newScheduledThreadPool (1 ). scheduleAtFixedRate (new Runnable () {public void run () {Integer serviceNumber = NumberMachine. getInstance (). getExpressManager (). generateNewNumber (); System. out. println ("no." + serviceNumber + ", the customer is waiting for service! ") ;}}, 0, Constants. COMMON_CUSTOMER_INTERVAL_TIME * 2, TimeUnit. SECONDS); // every six SECONDS, a VIP Customer takes the number (enable the timer) Executors. newScheduledThreadPool (1 ). scheduleAtFixedRate (new Runnable () {public void run () {Integer serviceNumber = NumberMachine. getInstance (). getVipManager (). generateNewNumber (); System. out. println ("no." + serviceNumber + "VIP customers are waiting for service! ") ;}}, 0, Constants. COMMON_CUSTOMER_INTERVAL_TIME * 6, TimeUnit. SECONDS );}}Use the for loop to create four normal windows, and then create one quick window and one VIP window.
Then, create three timers to regularly create new common customer numbers, new fast customer numbers, and new VIP Customer numbers.