线程函数需每2秒打印随机数且不阻塞主程序的技术问询
解决C++线程持续监控组件与主程序非阻塞问题
我来帮你搞定这个线程监控的问题,先梳理下原代码里的核心问题,再给出完整的修改方案:
原代码存在的几个关键问题:
- 线程用了
join(),直接阻塞主程序,没法同时操作添加/显示组件 - 线程函数找到组件后只执行一次
Read()就退出,没有持续循环打印 - 共享的
vector<component*>没有同步保护,主程序添加组件和线程遍历会有数据竞争 - 没有停止监控的触发机制,线程没法响应停止命令
下面是修改后的完整实现,关键改动都做了标注:
1. 补充component类定义
先把组件类补全,让Read()方法能生成并打印随机数:
#include <iostream> #include <vector> #include <thread> #include <chrono> #include <mutex> #include <atomic> #include <random> #include <string> using namespace std; // 定义组件类 class component { public: int type; int id; string name; component(int t, int i, string n) : type(t), id(i), name(n) {} // 生成并打印随机数的方法 void Read() { static random_device rd; static mt19937 gen(rd()); uniform_int_distribution<> dis(1, 100); cout << "[监控日志] 组件ID:" << id << " | 随机数:" << dis(gen) << endl; } };
2. 全局共享资源与同步变量
添加互斥锁保护vector,用原子变量做线程安全的停止标志:
vector<component*> v; mutex mtx; // 保护vector的互斥锁,避免数据竞争 atomic<bool> stopMonitoring(false); // 原子布尔变量,线程安全控制停止
3. 修改add函数,加锁保护共享容器
void add(int type, int id, string name) { lock_guard<mutex> lock(mtx); // 自动加锁解锁,防止忘记释放锁 v.push_back(new component(type, id, name)); cout << "组件添加成功:ID=" << id << ", 名称=" << name << endl; }
4. 实现display函数,加锁遍历组件列表
void display() { lock_guard<mutex> lock(mtx); if (v.empty()) { cout << "暂无组件数据" << endl; return; } cout << "\n===== 组件列表 =====" << endl; for (const auto& comp : v) { cout << "类型:" << comp->type << " | ID:" << comp->id << " | 名称:" << comp->name << endl; } cout << "====================" << endl; }
5. 修改线程函数,实现持续监控直到停止
现在线程会循环检查停止标志,找到目标组件后每2秒打印一次随机数:
void thread1(int targetId) { while (!stopMonitoring) { bool found = false; { lock_guard<mutex> lock(mtx); // 加锁访问vector,避免和主程序的添加操作冲突 for (const auto& comp : v) { if (comp->id == targetId) { comp->Read(); found = true; break; } } } // 锁在这里自动释放,避免sleep时持有锁影响主程序操作 if (!found) { cout << "[监控日志] 未找到ID=" << targetId << "的组件" << endl; } this_thread::sleep_for(chrono::seconds(2)); } cout << "[监控日志] ID=" << targetId << "的监控线程已停止" << endl; }
6. 修改主函数,支持非阻塞监控与停止操作
主程序不再被线程阻塞,启动线程后继续接收用户输入,停止时触发标志:
int main() { int choose; thread monitorThread; // 保存监控线程对象 bool isMonitoring = false; do { cout << "\n===== 操作菜单 =====" << endl; cout << "1. 添加组件" << endl; cout << "2. 显示组件" << endl; cout << "3. 开始监控" << endl; cout << "4. 停止监控" << endl; cout << "5. 退出程序" << endl; cout << "请选择操作:"; cin >> choose; switch (choose) { case 1: { int type, id; string name; cout << "请输入组件类型:"; cin >> type; cout << "请输入组件ID:"; cin >> id; cout << "请输入组件名称:"; cin >> name; add(type, id, name); break; } case 2: { display(); break; } case 3: { if (isMonitoring) { cout << "已有监控线程在运行,请先停止当前监控" << endl; break; } int id; cout << "请输入要监控的组件ID:"; cin >> id; stopMonitoring = false; // 重置停止标志 monitorThread = thread(thread1, id); monitorThread.detach(); // 线程后台运行,不阻塞主程序 isMonitoring = true; cout << "已启动ID=" << id << "的组件监控,每2秒打印一次随机数" << endl; break; } case 4: { if (!isMonitoring) { cout << "当前没有监控线程在运行" << endl; break; } stopMonitoring = true; isMonitoring = false; cout << "已发送停止监控命令,线程将在下次循环时停止" << endl; break; } case 5: { // 退出前先停止监控,避免线程泄漏 if (isMonitoring) { stopMonitoring = true; this_thread::sleep_for(chrono::seconds(1)); // 等待线程退出 } // 释放vector中的组件内存,避免内存泄漏 lock_guard<mutex> lock(mtx); for (auto comp : v) { delete comp; } v.clear(); cout << "程序已退出" << endl; break; } default: { cout << "无效选项,请重新选择" << endl; break; } } } while (choose != 5); return 0; }
关键改动说明
- 非阻塞线程:用
detach()替代join(),让监控线程后台运行,主程序可以正常处理用户的添加/显示操作 - 持续监控逻辑:线程函数通过
while (!stopMonitoring)循环,每次执行Read()后等待2秒 - 线程安全保护:用
std::mutex和lock_guard保护共享的vector,避免主程序添加组件和线程遍历的冲突 - 可控停止机制:用
atomic<bool>作为停止标志,线程安全地触发停止命令 - 资源清理:退出程序时释放组件内存,避免内存泄漏
现在这个代码完全满足你的需求:启动监控后每2秒打印对应组件的随机数,主程序可以正常添加/显示组件,点击停止监控后线程会自动终止。
内容的提问来源于stack exchange,提问作者inihsrah
相关产品推荐
相关产品推荐

