From 919e5f28b77de620845846f9f74e9583e7f3d436 Mon Sep 17 00:00:00 2001 From: frsama <108132842+frsama@users.noreply.github.com> Date: Tue, 9 Aug 2022 15:52:14 +0800 Subject: [PATCH] Update main.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.将和用户相关的若干变量、结构体和函数封装成了类。 2.给用户类的几个哈希表上了锁。 3.将线程池改为类实现,丰富了功能。线程池改为常驻固定个数的工作线程,使用了条件变量,任务队列中无任务时工作线程会一直wait。 --- main.cpp | 164 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 118 insertions(+), 46 deletions(-) diff --git a/main.cpp b/main.cpp index f4ecab8..f3a33e9 100644 --- a/main.cpp +++ b/main.cpp @@ -2,68 +2,139 @@ #include #include #include -#include #include #include #include +#include +#include +#include +#include +#define MAX_THREAD_N 8 -struct User { - std::string password; - std::string school; - std::string phone; -}; +//改用类实现,原来的几个变量、数据结构和函数都是强耦合关系,应该封装在一起 +class Users { + struct User { + std::string password; + std::string school; + std::string phone; + }; -std::map users; -std::map has_login; // 换成 std::chrono::seconds 之类的 - -// 作业要求1:把这些函数变成多线程安全的 -// 提示:能正确利用 shared_mutex 加分,用 lock_guard 系列加分 -std::string do_register(std::string username, std::string password, std::string school, std::string phone) { - User user = {password, school, phone}; - if (users.emplace(username, user).second) - return "注册成功"; - else - return "用户名已被注册"; -} + std::map users; + std::map has_login; // 换成 std::chrono::seconds 之类的 + std::shared_mutex users_mtx; + std::shared_mutex has_login_mtx; -std::string do_login(std::string username, std::string password) { - // 作业要求2:把这个登录计时器改成基于 chrono 的 - long now = time(NULL); // C 语言当前时间 - if (has_login.find(username) != has_login.end()) { - int sec = now - has_login.at(username); // C 语言算时间差 - return std::to_string(sec) + "秒内登录过"; +public: + // 作业要求1:把这些函数变成多线程安全的 + // 提示:能正确利用 shared_mutex 加分,用 lock_guard 系列加分 + std::string do_register(std::string username, std::string password, std::string school, std::string phone) { + std::cout << "in do_register" << std::endl; + User user = {password, school, phone}; + std::unique_lock lck(users_mtx); + if (users.emplace(username, user).second) + return "注册成功"; + else + return "用户名已被注册"; } - has_login[username] = now; - if (users.find(username) == users.end()) - return "用户名错误"; - if (users.at(username).password != password) - return "密码错误"; - return "登录成功"; -} + std::string do_login(std::string username, std::string password) { + // 作业要求2:把这个登录计时器改成基于 chrono 的 + std::cout<<"in do_login"<(dt).count(); + return std::to_string(sec) + "秒内登录过"; + } + s_lck1.unlock(); -std::string do_queryuser(std::string username) { - auto &user = users.at(username); - std::stringstream ss; - ss << "用户名: " << username << std::endl; - ss << "学校:" << user.school << std::endl; - ss << "电话: " << user.phone << std::endl; - return ss.str(); -} + std::unique_lock u_lck1(has_login_mtx); + has_login[username] = now; + u_lck1.unlock(); + + std::shared_lock s_lck2(users_mtx); + if (users.find(username) == users.end()) + return "用户名错误"; + if (users.at(username).password != password) + return "密码错误"; + return "登录成功"; + } + + std::string do_queryuser(std::string username) { + std::cout<<"in do_queryuser"< start) { +//改用类实现 +class ThreadPool { + int thread_num; + std::vector threads; + bool activate;//用来关闭工作线程 + + std::queue> missions_queue; + std::mutex mtx;//用来独占missions_queue + std::condition_variable cv;//用来控制工作线程等待任务队列 + +public: + ThreadPool(int num = MAX_THREAD_N):thread_num(num), threads(num), activate(true){ + for(int i = 0; i start) + { // 作业要求3:如何让这个线程保持在后台执行不要退出? // 提示:改成 async 和 future 且用法正确也可以加分 - std::thread thr(start); + //用cv改成工作线程常驻,等待任务队列的形式。 + std::unique_lock lck(mtx); + missions_queue.push(start); + lck.unlock(); + cv.notify_one(); + } + + void working(){ + std::unique_lock lck(mtx); + while(activate){ + if(missions_queue.size()==0){ + cv.wait(lck); + continue; + } + std::function f{[](){}}; + f = missions_queue.front(); + missions_queue.pop(); + lck.unlock(); + f(); + lck.lock(); + } } }; ThreadPool tpool; - namespace test { // 测试用例?出水用力! std::string username[] = {"张心欣", "王鑫磊", "彭于斌", "胡原名"}; std::string password[] = {"hellojob", "anti-job42", "cihou233", "reCihou_!"}; @@ -74,16 +145,17 @@ std::string phone[] = {"110", "119", "120", "12315"}; int main() { for (int i = 0; i < 262144; i++) { tpool.create([&] { - std::cout << do_register(test::username[rand() % 4], test::password[rand() % 4], test::school[rand() % 4], test::phone[rand() % 4]) << std::endl; + std::cout << users.do_register(test::username[rand() % 4], test::password[rand() % 4], test::school[rand() % 4], test::phone[rand() % 4]) << std::endl; }); tpool.create([&] { - std::cout << do_login(test::username[rand() % 4], test::password[rand() % 4]) << std::endl; + std::cout << users.do_login(test::username[rand() % 4], test::password[rand() % 4]) << std::endl; }); tpool.create([&] { - std::cout << do_queryuser(test::username[rand() % 4]) << std::endl; + std::cout << users.do_queryuser(test::username[rand() % 4]) << std::endl; }); } // 作业要求4:等待 tpool 中所有线程都结束后再退出 + // 结束自动调用析构函数,析构函数会逐个join return 0; }