You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

线程函数需每2秒打印随机数且不阻塞主程序的技术问询

解决C++线程持续监控组件与主程序非阻塞问题

我来帮你搞定这个线程监控的问题,先梳理下原代码里的核心问题,再给出完整的修改方案:

原代码存在的几个关键问题:

  1. 线程用了join(),直接阻塞主程序,没法同时操作添加/显示组件
  2. 线程函数找到组件后只执行一次Read()就退出,没有持续循环打印
  3. 共享的vector<component*>没有同步保护,主程序添加组件和线程遍历会有数据竞争
  4. 没有停止监控的触发机制,线程没法响应停止命令

下面是修改后的完整实现,关键改动都做了标注:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:39:08