每一个窗口对应一个线程,还是存在一些关于并发的问题,用户都是随机数生成,无法模拟实际情况,互斥锁锁住之后,存在只有一个线程掌握资源的情况。试图解决方案,把互斥锁,条件变量全部封装到一个类,模拟单生产者,多消费者模型。
或者修改成几个窗口,几个队列
main.cpp
//
// main.cpp
// 模拟银行排队
//
// Created by 蓝猫 on 2019/3/15.
// Copyright © 2019年 蓝猫. All rights reserved.
//
/*
业务逻辑:
首先我们要分析银行提供服务的逻辑。在银行服务中,所有顾客都是通过取号排队的方式等待服务的,这和火车站买票有所不同,在火车站买票时,顾客必须在某一个窗口所排的队列下进行排队,且无法变更自己所属的窗口,否则只能从队尾重新排队。换句话说,对于银行提供的服务来说,所有用户都是位于同一个队列上的,当某个服务窗口可用时,才会从排队队列的队首取出一个新的用户来办理银行业务。即代码实现过程中,服务窗口可以创建 w 个,但只需要实现一个顾客队列即可。
其次,对于顾客而言,有两个属性是能够被抽象出来的:
到达银行的时间;
需要服务的时间。
感觉类似线程池,每一个顾客是任务,
*/
#include
#include
#include "Bank.hpp"
static std::string getCurrentTimeStr()
{
time_t t = time(NULL);
char ch[64] = {0};
strftime(ch, sizeof(ch) - 1, "%Y-%m-%d %H:%M:%S", localtime(&t)); //年-月-日 时-分-秒
return ch;
}
int main(int argc, const char * argv[])
{
const int win_num=3;
//std::cout << getCurrentTimeStr()<<"\n";
int time1,time2;
std::cout<<"======================欢迎光临蓝猫银行======================"<>time1>>time2;
Bank b(time1,time2,win_num);
//b.Main();
b. Main_thread();
return 0;
}
Bank.cpp&&hpp
//
// Bank.hpp
// 模拟银行排队
//
// Created by 蓝猫 on 2019/3/18.
// Copyright © 2019年 蓝猫. All rights reserved.
//
#ifndef Bank_hpp
#define Bank_hpp
#include
#include
#include
#include
#include
#include
#include
#include
#include "Customer.hpp"
#include "Win.hpp"
class Bank
{
private:
bool exit;//是否销毁所有线程
std::mutex mutex_t;
std::condition_variable cond;//队列空的条件变量
//std::condition_variable conds;//每个窗口繁忙的条件变量
std::vector wins_thread;//线程窗口 每个线程对应下标相同的窗口
int open_time;//开门时间 输入多少 就是几点
int close_time;//关门时间 输入多少 就是几点
int close_time2;//关门时间 开门后分钟
int last;// 转换成开门后的分钟 最后被允许取号的时间
int arr_time;//( 上一个顾客来的时间) 通过它来随机产生顾客顺序到来
int num_customer;//顾客数量
int num_win;//窗口数量
std::vector win_v;//窗口数量
std::queue que;//顾客队列
public:
Bank(int t1,int t2,int num):open_time(t1),close_time(t2),num_win(num)
{
close_time2=(close_time-open_time)*60;
last=(close_time-open_time)*60-20;//提前二十分钟不能取号
arr_time=0;
num_customer=0;
for(int i=0;i
//
// Bank.cpp
// 模拟银行排队
//
// Created by 蓝猫 on 2019/3/18.
// Copyright © 2019年 蓝猫. All rights reserved.
//
#include "Bank.hpp"
using namespace std;
void Bank::Create_Customer_thread()//;//多线程版本 产生用户放入队列 需要一个生产者线程
{
while (1)
{
int arrive = rand() % 8 + 1 + arr_time;//随机产生一个用户进入队列 1-8内来一个
std::this_thread::sleep_for(std::chrono::milliseconds(arrive- arr_time+500));
//std::this_thread::sleep_for(std::chrono::seconds(arrive- arr_time));
if (arrive > close_time2)
{
print_time(arrive);
cout << "已经关门了 明个再来" << endl;
exit = true;
break;
}
arr_time = arrive;
//bool empty = que.empty();//判断之前是否为空
std::unique_lock lk(mutex_t);//锁住
Customer cust(num_customer, arrive);//多线程版本 办理业务时间在线程函数中生成
que.push(cust);
num_customer++;
cond.notify_one();
}
}
void Bank:: Create_thread()
{
for (int i = 0; i < num_win; i++)
{
printf("窗口%d就绪\n",i+1);
wins_thread.emplace_back(std::thread(&Bank::Customer_into_thread,this,i));
std::condition_variable temp;
//conds.push_back(temp);
}
};
void Bank:: Del_thread() //中止线程
{
for (int i = 0; i < wins_thread.size(); i++)
{
wins_thread[i].join();
}
}
void Bank:: Customer_into_thread(int i)//;//顾客处理函数 i窗口下标
{
while (1)
{
std::unique_lock lk(mutex_t);//互斥锁 锁住
//事实上用于不会很忙
while (que.empty()||win_v[i].is_busy())//如果队列空或者窗口很忙 等待
{
//if(win_v[i].is_busy())printf("窗口%d繁忙\n",i+1);
//if(que.empty())printf("队列空 窗口%d空闲\n",i+1);
cond.wait(lk);
}
if (que.empty() && exit)
{
cond.notify_all();
break;//银行下班了
}
//不忙且队列不空
Customer c = que.front();
que.pop();
//lk.unlock();
if (c.get_arrive_time() > last)
{
cout << c.get_id() << "号 到达:";
print_time(c.get_arrive_time());
cout << "准备关门了 明个再来" << endl;
cond.notify_all();
}
else
{
int process = rand() % 20 + 1 + 5;//业务办理时间 5-25min
c.set_process_time(process);
Win_Customer_thread(i, c);
}
}
//Del_thread();
}
void Bank::Win_Customer_thread(int pos,Customer c)//顾客办理业务 这个w必须传实参 因为窗口会变的
{
win_v[pos].set_busy();
c.set_wait_time(win_v[pos].get_last_time());
cout<<"窗口:"<close_time2)
{
print_time(arrive);
cout<<"已经关门了 明个再来"<last)
{
cout<<"准备关门了 明个再来"<last)
{
cout<(x.get_last_time()-c.get_arrive_time()))
{
//cout<<"wait"<
Customer.hpp&&cpp cpp空
//
// Customer.hpp
// 模拟银行排队
//
// Created by 蓝猫 on 2019/3/15.
// Copyright © 2019年 蓝猫. All rights reserved.
//
#ifndef Customer_hpp
#define Customer_hpp
#include
#include
#include
using namespace std;
class Customer
{
private:
//时间全部为开门之后的多少分钟
int id;//顾客id
//int win;//在那个窗口办理
int arrive_time;//到达时间
int leave_time;//离开时间
int wait_time;//等待时间
int start_time;//开始办理业务时间
int process_time;//办理业务过程时间
int total_time;//在银行呆的时间
public:
Customer(int num,int time1,int time2):id(num),arrive_time(time1),process_time(time2)
{
};
Customer(int num, int time1) :id(num), arrive_time(time1)//多线程版本 业务时间不着急产生
{
};
inline int get_id()
{
return id;
}
//到达时间
inline void set_arrive_time(int time)
{
arrive_time=time;
}
inline int get_arrive_time()
{
return arrive_time;
}
//离开时间
inline int get_leave_time()
{
leave_time=start_time+process_time;
return leave_time;
}
//业务开始时间
inline int get_start_time()
{
return start_time;
}
//等待时机
inline void set_wait_time(int time)//参数是窗口上一个用户结束时间
{
if(arrive_time>=time)//不用等待
{
wait_time=0;
}
else
{
wait_time=time-arrive_time;
}
start_time=arrive_time+wait_time;
}
inline int get_wait_time()
{
return wait_time;
}
//业务时机
inline void set_process_time(int time)
{
process_time=time;
}
inline int get_process_time()
{
return process_time;
}
//总时间
inline int get_total_time()
{
return leave_time-arrive_time;
}
};
#endif /* Customer_hpp */
Win.hpp&&cpp cpp为空
//
// Win.hpp
// 模拟银行排队
//
// Created by 蓝猫 on 2019/3/18.
// Copyright © 2019年 蓝猫. All rights reserved.
//
#ifndef Win_hpp
#define Win_hpp
#include
class Win
{
private:
int num;//窗口号码
bool isbusy;
int last_time;//上一个刚结束的时间
public:
Win()
{
isbusy=false;
last_time=0;
};
void set_num(int n)
{
num=n;
}
void set_busy()
{
isbusy=true;
}
void set_nobusy()
{
isbusy=false;
}
void set_last_time(int time)
{
last_time=time;
}
inline int get_last_time()
{
return last_time;
}
inline int get_num()
{
return num;
}
inline bool is_busy()
{
return isbusy;
}
};
#endif /* Win_hpp */
结果
======================欢迎光临蓝猫银行======================
请输入银行开门和关门时间,9:00-12:00,请输入9 12
窗口数量:3
9 12
窗口1就绪
窗口2就绪
窗口3就绪
窗口:2 0号 到达:9:8 离开:9:27 等待:0 开始办理:9:8 业务时间:19 总时间:19
窗口:1 1号 到达:9:10 离开:9:26 等待:0 开始办理:9:10 业务时间:16 总时间:16
窗口:3 2号 到达:9:13 离开:9:23 等待:0 开始办理:9:13 业务时间:10 总时间:10
窗口:2 3号 到达:9:14 离开:9:36 等待:13 开始办理:9:27 业务时间:9 总时间:22
窗口:1 4号 到达:9:21 离开:9:32 等待:5 开始办理:9:26 业务时间:6 总时间:11
窗口:3 5号 到达:9:27 离开:9:45 等待:0 开始办理:9:27 业务时间:18 总时间:18
窗口:2 6号 到达:9:33 离开:9:49 等待:3 开始办理:9:36 业务时间:13 总时间:16
窗口:1 7号 到达:9:36 离开:9:49 等待:0 开始办理:9:36 业务时间:13 总时间:13
窗口:3 8号 到达:9:44 离开:9:51 等待:1 开始办理:9:45 业务时间:6 总时间:7
窗口:2 9号 到达:9:46 离开:9:58 等待:3 开始办理:9:49 业务时间:9 总时间:12
窗口:1 10号 到达:9:51 离开:10:6 等待:0 开始办理:9:51 业务时间:15 总时间:15
窗口:3 11号 到达:9:53 离开:9:59 等待:0 开始办理:9:53 业务时间:6 总时间:6
窗口:2 12号 到达:9:59 离开:10:24 等待:0 开始办理:9:59 业务时间:25 总时间:25
窗口:1 13号 到达:10:5 离开:10:28 等待:1 开始办理:10:6 业务时间:22 总时间:23
窗口:3 14号 到达:10:12 离开:10:35 等待:0 开始办理:10:12 业务时间:23 总时间:23
窗口:2 15号 到达:10:20 离开:10:42 等待:4 开始办理:10:24 业务时间:18 总时间:22
窗口:1 16号 到达:10:23 离开:10:44 等待:5 开始办理:10:28 业务时间:16 总时间:21
窗口:3 17号 到达:10:27 离开:11:0 等待:8 开始办理:10:35 业务时间:25 总时间:33
窗口:2 18号 到达:10:29 离开:11:7 等待:13 开始办理:10:42 业务时间:25 总时间:38
窗口:1 19号 到达:10:35 离开:10:57 等待:9 开始办理:10:44 业务时间:13 总时间:22
窗口:3 20号 到达:10:41 离开:11:19 等待:19 开始办理:11:0 业务时间:19 总时间:38
窗口:2 21号 到达:10:42 离开:11:18 等待:25 开始办理:11:7 业务时间:11 总时间:36
窗口:1 22号 到达:10:43 离开:11:11 等待:14 开始办理:10:57 业务时间:14 总时间:28
窗口:3 23号 到达:10:45 离开:11:39 等待:34 开始办理:11:19 业务时间:20 总时间:54
窗口:2 24号 到达:10:49 离开:11:25 等待:29 开始办理:11:18 业务时间:7 总时间:36
窗口:1 25号 到达:10:55 离开:11:25 等待:16 开始办理:11:11 业务时间:14 总时间:30
窗口:3 26号 到达:10:57 离开:11:53 等待:42 开始办理:11:39 业务时间:14 总时间:56
窗口:2 27号 到达:10:58 离开:11:35 等待:27 开始办理:11:25 业务时间:10 总时间:37
窗口:1 28号 到达:11:1 离开:11:41 等待:24 开始办理:11:25 业务时间:16 总时间:40
窗口:3 29号 到达:11:6 离开:12:1 等待:47 开始办理:11:53 业务时间:8 总时间:55
窗口:2 30号 到达:11:14 离开:11:50 等待:21 开始办理:11:35 业务时间:15 总时间:36
窗口:1 31号 到达:11:17 离开:11:48 等待:24 开始办理:11:41 业务时间:7 总时间:31
窗口:3 32号 到达:11:18 离开:12:24 等待:43 开始办理:12:1 业务时间:23 总时间:66
窗口:2 33号 到达:11:24 离开:12:4 等待:26 开始办理:11:50 业务时间:14 总时间:40
窗口:1 34号 到达:11:25 离开:12:12 等待:23 开始办理:11:48 业务时间:24 总时间:47
窗口:3 35号 到达:11:31 离开:12:45 等待:53 开始办理:12:24 业务时间:21 总时间:74
窗口:2 36号 到达:11:37 离开:12:15 等待:27 开始办理:12:4 业务时间:11 总时间:38
37号 到达:11:43 准备关门了 明个再来
38号 到达:11:50 准备关门了 明个再来
39号 到达:11:58 准备关门了 明个再来
40号 到达:11:59 准备关门了 明个再来
12:1 已经关门了 明个再来