這是一個模拟銀行視窗排隊叫号排程系統,參考了網上兩篇文章,一篇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[];
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() % + ;
if (type <= )
return Client::CLIENT_COMMON;
else if (type >= && type <= )
return Client::CLIENT_FAST;
return Client::CLIENT_VIP;
}
int createTasktime() {
return rand() % MAX_SERVICE_TIME + ;
}
void createClient() {
Client::ClientType clientType;
int taskTime;
for (int i = ; 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();
}
}
unsigned __stdcall serviceWin(void *win) {
ServiceWin *serWin = static_cast<ServiceWin*> (win);
serWin->execute();
TerminateThread(thread_Map[serWin->getCount()],);
return ;
}
bool createServiceWin(HANDLE thread1[],HANDLE &thread2,HANDLE &thread3) {
unsigned commonServiceWin[];
unsigned fastServiceWin;
unsigned vipServiceWin;
char tmp[]={};
ServiceWin *win;
for (int i = ; i < ; ++i) {
sprintf(tmp, "CommonWin%d", i);
win = new CommonSerWin(tmp);
if (win == NULL) {
std::cout << "Create common service win error." << std::endl;
return -;
}
win->setCount(i);
//_beginthreadex傳回handle
if ((thread1[i] = (HANDLE)_beginthreadex(NULL, ,serviceWin, (void*) win,,&commonServiceWin[i]) )== ) {
std::cout << "Create common service thread error." << std::endl;
return false;
}
thread_Map.insert(map<int,HANDLE>::value_type(i,thread1[i]));
}
memset(tmp,,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, ,serviceWin, (void*) win,,NULL/*&fastServiceWin*/)) == ) {
std::cout << "Create fast service thread error." << std::endl;
return false;
}
thread_Map.insert(map<int,HANDLE>::value_type(THREAD2,thread2));
memset(tmp,,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, ,serviceWin, (void*) win,,&vipServiceWin)) == ) {
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());
if (!createServiceWin(thread1,thread2,thread3)) {
std::cout << "Create service win error." << std::endl;
return -;
}
createClient();
for(int i = ; i<; i++)
WaitForSingleObject(thread1[i],INFINITE);
WaitForSingleObject(thread2,INFINITE);
WaitForSingleObject(thread3,INFINITE);
delete NumMachine::getInstance();
for(int i = ; i<; i++)
CloseHandle(thread1[i]);
CloseHandle(thread2);
CloseHandle(thread3);
}
numberMachine.cpp
#include "StdAfx.h"
#include "numMachine.h"
NumMachine * NumMachine::numMachine = new NumMachine;
NumMachine::NumMachine() :
leaveClient(), total(), handledClient() {
// pthread_mutex_init(&clientListLock, NULL);
clientListLock=CreateMutex(NULL,false,NULL);
clientPressLock=CreateMutex(NULL,false,NULL);
m_CommerSem=CreateSemaphore(NULL, , , NULL);//目前個資源,最大允許個同時通路
m_FastSem=CreateSemaphore(NULL, , , NULL);//目前個資源,最大允許個同時通路
m_VipSem=CreateSemaphore(NULL, , , 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(-);
}
clientList.push_back(c);
//semaphore
ReleaseSemaphore(m_map[clientType],,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],);
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],);
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 () {
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 () {
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 () {
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;
}
}
}
}
執行結果:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICO5UDMzkTN5EzMycDM1EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
完整程式下載下傳位址:
http://download.csdn.net/detail/luomoshusheng/8927561