银行窗口排队叫号系统实现 - Go语言中文社区

银行窗口排队叫号系统实现


这是一个模拟银行窗口排队叫号调度系统,参考了网上两篇文章,一篇java的和一篇linux c++的,然后我在windows下实现了它,开发工具是vs2008.在文章最后我会给出直接可编译可执行代码。

Java版参考:http://blog.csdn.net/zhangxiaoxiang/article/details/6294132
Linux c++版参考:http://blog.csdn.net/yanjiashang/article/details/6359652

模拟实现银行业务调度系统逻辑,具体需求如下:
• 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
• 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
• 异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIP客户:普通客户:快速客户 = 1 :6 :3。
• 客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
• 各类型客户在其对应窗口按顺序依次办理业务。
• 当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
• 随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
分析,注意一下几点:
1、 其实实现方法还是挺多的,可以用3个队列分别表示vip,fast和commer,也可以只用一个list,直接在里面找,我就只用了一个list。
2、 NumberMachine要设计为单例类。
3、 注意同步与互斥的问题,同时避免死锁。当表为空时,即每人来的的时候,线程应该在等待资源,而不是一直在循环。最后假设银行一天最多只能处理50个人最为终结条件。

代码关键的地方有加点注释,我觉得不需要解释还是可以看懂了,那就直接上代码吧,文章最后会把完整程序一并给出。同时,需要看到程序有什么不妥的地方请指出,互相探讨,共同进步。

Bank_queue.cpp

#include "stdafx.h"

#include <iostream>  
#include <process.h>

#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  
#include "numMachine.h"  
#include "serviceWin.h"  
#include "client.h"  
#include "constances.h"  
using namespace std;

HANDLE thread1[4];
HANDLE thread2;
HANDLE thread3;
map<int,HANDLE> thread_Map;
enum ID{
    THREAD1_0,THREAD1_1,THREAD1_2,THREAD1_3,THREAD2,THREAD3
};

Client::ClientType createClientType() {  
    int type;  
    type = rand() % 10 + 1;  
    if (type <= 6)  
        return Client::CLIENT_COMMON;  
    else if (type >= 7 && type <= 9)  
        return Client::CLIENT_FAST;  
    return Client::CLIENT_VIP;  
}  
int createTasktime() {  
    return rand() % MAX_SERVICE_TIME + 1;  
}  
void createClient() {  
    Client::ClientType clientType;  
    int taskTime;  
    for (int i = 0; i < MAX_CLIENT_NUM; ++i) {  
        clientType = createClientType();  
        taskTime = createTasktime();  
        std::cout << "Come in a client : clientType = " << clientType  
            << " taskTime = " << taskTime << std::endl;  
        NumMachine::getInstance()->pressMachine(clientType, taskTime);  
        Sleep(1);

    }  
}  
unsigned  __stdcall serviceWin(void *win) {  
    ServiceWin *serWin = static_cast<ServiceWin*> (win);    
    serWin->execute(); 
    TerminateThread(thread_Map[serWin->getCount()],0);
    return 0;
}  
bool createServiceWin(HANDLE thread1[],HANDLE &thread2,HANDLE &thread3) {    
    unsigned commonServiceWin[4];  
    unsigned fastServiceWin;  
    unsigned vipServiceWin;  

    char tmp[20]={0};  
    ServiceWin *win;  
    for (int i = 0; i < 4; ++i) {  
        sprintf(tmp, "CommonWin%d", i);  
        win = new CommonSerWin(tmp);  
        if (win == NULL) {  
            std::cout << "Create common service win error." << std::endl;  
            return -1;  
        }
        win->setCount(i);
        //_beginthreadex返回handle
        if ((thread1[i] = (HANDLE)_beginthreadex(NULL, 0,serviceWin, (void*) win,0,&commonServiceWin[i]) )== 0) {  
                std::cout << "Create common service thread error." << std::endl;  
                return false;  
        }
        thread_Map.insert(map<int,HANDLE>::value_type(i,thread1[i]));

    }  
    memset(tmp,0,sizeof(tmp));
    sprintf(tmp, "FastWin");  
    win = new FastSerWin(tmp);  
    if (win == NULL) {  
        std::cout << "Create fast service win error." << std::endl;  
        return false;  
    }  
    win->setCount(THREAD2);
    if ((thread2 = (HANDLE )_beginthreadex(NULL, 0,serviceWin, (void*) win,0,NULL/*&fastServiceWin*/)) == 0) {  
        std::cout << "Create fast service thread error." << std::endl;  
        return false;  
    }
    thread_Map.insert(map<int,HANDLE>::value_type(THREAD2,thread2));
    memset(tmp,0,sizeof(tmp));
    sprintf(tmp, "VipWin");  
    win = new VipSerWin(tmp);  
    if (win == NULL) {  
        std::cout << "Create vip service win error." << std::endl;  
        return false;  
    }  
    win->setCount(THREAD3);
    if ((thread3 = (HANDLE)_beginthreadex(NULL, 0,serviceWin, (void*) win,0,&vipServiceWin)) == 0) {  
        std::cout << "Create vip service thread error." << std::endl;  
        return false;  
    }  
    thread_Map.insert(map<int,HANDLE>::value_type(THREAD3,thread3));
    return true;  
}  
int _tmain(int argc, char *argv[]) {  
    std::cout << "/***start : please wait 5 seconds when progress suspend *****/" << std::endl;  


    srand((unsigned) time(0));  
    if (!createServiceWin(thread1,thread2,thread3)) {  
        std::cout << "Create service win error." << std::endl;  
        return -1;  
    }  
    createClient();  

    for(int i = 0; i<4; i++)
        WaitForSingleObject(thread1[i],INFINITE);
    WaitForSingleObject(thread2,INFINITE);
    WaitForSingleObject(thread3,INFINITE);
    delete NumMachine::getInstance();  
    for(int i = 0; i<4; i++)
        CloseHandle(thread1[i]);
    CloseHandle(thread2);
    CloseHandle(thread3);
}  

numberMachine.cpp

#include "StdAfx.h"
#include "numMachine.h"

NumMachine * NumMachine::numMachine = new NumMachine;  
NumMachine::NumMachine() :  
leaveClient(0), total(0), handledClient(0) {  
//  pthread_mutex_init(&clientListLock, NULL);  
    clientListLock=CreateMutex(NULL,false,NULL);
    clientPressLock=CreateMutex(NULL,false,NULL);
    m_CommerSem=CreateSemaphore(NULL, 0, 50, NULL);//当前个资源,最大允许个同时访问
    m_FastSem=CreateSemaphore(NULL, 0, 50, NULL);//当前个资源,最大允许个同时访问
    m_VipSem=CreateSemaphore(NULL, 0, 50, NULL);//当前个资源,最大允许个同时访问
    m_map.insert(map<Client::ClientType,HANDLE>::value_type(Client::CLIENT_COMMON,m_CommerSem));
    m_map.insert(map<Client::ClientType,HANDLE>::value_type(Client::CLIENT_FAST,m_FastSem));
    m_map.insert(map<Client::ClientType,HANDLE>::value_type(Client::CLIENT_VIP,m_VipSem));

}  
NumMachine::~NumMachine() {  
    std::cout << "/**********     end         ****************/" << std::endl;  
    std::cout << "The number of total client is " << total << std::endl;  
    std::cout << "The number of handled client is " << handledClient << std::endl;  
    std::cout << "The number of waiting client is " << clientList.size() << std::endl;  
    std::cout << "The number of client is " << leaveClient  
        << " ,because waiting time too long." << std::endl;  
    for_each(clientList.begin(), clientList.end(), DelClientList()); 
    CloseHandle(clientListLock);
}  
NumMachine * NumMachine::getInstance() {  
    return numMachine;  
}  
void NumMachine::pressMachine(Client::ClientType clientType, int taskTime) {  
    ++total;  
    if (clientList.size() < MAX_WAITING_CLIENT_NUM) {  
        Client * c = new Client(clientType, taskTime);  
        if (c == NULL) {  
            ReleaseMutex(clientPressLock);
            std::cout << "Can't create Client" << std::endl;  
            exit(-1);  
        }  
        clientList.push_back(c);  
        //semaphore
        ReleaseSemaphore(m_map[clientType],1,NULL);
    } else {  
        ++leaveClient;  
    }
}  
int NumMachine::getTotal(){
    return total;
}

Client * NumMachine::removeClient(Client::ClientType val) {  
    std::list<Client*>::iterator pos;  
    Client *tmp;  
    if (total == MAX_CLIENT_NUM)
    {
        DWORD rtn = WaitForSingleObject(m_map[val],1000);
        if (WAIT_TIMEOUT == rtn)
        {
#ifdef DEBUG
            std::cout<<"val:"<<val<<",rtn:WAIT_TIMEOUT"<<std::endl; 
#endif
            return NULL;
        }
        if (WAIT_ABANDONED == rtn)
        {
#ifdef DEBUG
            std::cout<<"val:"<<val<<",rtn:WAIT_ABANDONED"<<std::endl;
#endif
            return NULL;
        }
        if (WAIT_FAILED == rtn)
        {
#ifdef DEBUG
            std::cout<<"val:"<<val<<",rtn:WAIT_FAILED"<<std::endl;
#endif
            return NULL;
        }
    }else{
        DWORD rtn = WaitForSingleObject(m_map[val],3000);
        if (WAIT_TIMEOUT == rtn)
        {
#ifdef DEBUG
            std::cout<<" total < MAX_CLIENT_NUM val:"<<val<<",rtn:WAIT_TIMEOUT"<<std::endl;     
#endif
        }
        if (WAIT_ABANDONED == rtn)
        {
#ifdef DEBUG
            std::cout<<"total < MAX_CLIENT_NUM val:"<<val<<",rtn:WAIT_ABANDONED"<<std::endl;
#endif
        }
        if (WAIT_FAILED == rtn)
        {
#ifdef DEBUG
            std::cout<<"total < MAX_CLIENT_NUM val:"<<val<<",rtn:WAIT_FAILED"<<std::endl;
#endif
        }
    }
    WaitForSingleObject(clientListLock,INFINITE);
    pos = find_if(clientList.begin(), clientList.end(), FindClient(val));  
    if (pos != clientList.end()) {  

        ++handledClient;  
        tmp = *pos; 
        clientList.erase(pos); 
        ReleaseMutex(clientListLock);

        return tmp;  
    } else {   
        ReleaseMutex(clientListLock);   
        return NULL;  
    }  
}  
void DelClientList::operator ()(Client *item) {  
    std::cout << "Waiting client : clientType =" << item->getClientType()  
        << " taskTime = " << item->getServiceTime() << std::endl;  
    delete item;  
}  
FindClient::FindClient(Client::ClientType t) :  
clientType(t) {  
}  
bool FindClient::operator ()(Client * item) {  
    if (item->getClientType() == clientType)  
        return true;  
    else  
        return false;  
}  

serviceWin.cpp

#include "stdafx.h"
#include "serviceWin.h"  
ServiceWin::ServiceWin(std::string n) :  
winName(n) {  
}  
ServiceWin::~ServiceWin() {  
}  
std::string ServiceWin::getWinName() {  
    return winName;  
}  
CommonSerWin::CommonSerWin(std::string n) :  
ServiceWin(n) {  
}  
CommonSerWin::~CommonSerWin() {  
}  
void CommonSerWin::execute() {  
    Client * client = NULL;  
    while (1) {  
        client = NumMachine::getInstance()->removeClient(Client::CLIENT_COMMON);  
        if (client != NULL) {  
            std::cout << "A client be handled : clientType = " << client->getClientType()  
                << " taskTime = " << client->getServiceTime() << " "<< getWinName()<< std::endl;  
            Sleep(client->getServiceTime());  
            delete client;  
        }else{
            if (MAX_CLIENT_NUM == NumMachine::getInstance()->getTotal())
            {
                return;
            }
        }  
    }  
}  
FastSerWin::FastSerWin(std::string n) :  
ServiceWin(n) {  
}  
FastSerWin::~FastSerWin() {  
}  
void FastSerWin::execute() {  
    Client * client = NULL;  
    while (1) {  
        client = NumMachine::getInstance()->removeClient(Client::CLIENT_FAST);  
        if (client != NULL) {  
            std::cout << "A client be handled : clientType = " << client->getClientType()  
                << " taskTime = " << client->getServiceTime() << " "<< getWinName() << std::endl;  
            Sleep(client->getServiceTime());  
            delete client;  
        }else{
            if (MAX_CLIENT_NUM == NumMachine::getInstance()->getTotal())
            {
                return;
            }
        }    
    }  
}  
VipSerWin::VipSerWin(std::string n) :  
ServiceWin(n) {  
}  
VipSerWin::~VipSerWin() {  
}  
void VipSerWin::execute() {  
    Client * client = NULL;  
    while (1) {  
        client = NumMachine::getInstance()->removeClient(Client::CLIENT_VIP);  
        if (client != NULL) {  
            std::cout << "A client be handled : clientType = " << client->getClientType()  
                << " taskTime = " << client->getServiceTime() << " "<< getWinName() << std::endl;  
            Sleep(client->getServiceTime());  
            delete client;  
        }else{
            if (MAX_CLIENT_NUM == NumMachine::getInstance()->getTotal())
            {
                return;
            }
        }    
    }  
}  

执行结果:
result
完整程序下载地址:
http://download.csdn.net/detail/luomoshusheng/8927561

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/luomoshusheng/article/details/47027539
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-09-13 20:20:12
  • 阅读 ( 1277 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

推荐文章

猜你喜欢