C++ 在类中创建并使用线程

举报
福州司马懿 发表于 2024/06/30 12:42:10 2024/06/30
【摘要】 thread库在C++中,你可以使用<thread>库来在类中创建线程。然而,直接在类的成员函数中启动线程可能不是一个好主意,因为线程的生命周期和对象的生命周期可能会变得难以管理。但你可以通过在类的成员函数或成员变量中封装线程创建的逻辑来实现这一功能。 简单线程示例以下是一个简单的示例,展示了如何在C++类的成员函数中启动一个线程:#include <iostream>#include <...

thread库

在C++中,你可以使用<thread>库来在类中创建线程。然而,直接在类的成员函数中启动线程可能不是一个好主意,因为线程的生命周期和对象的生命周期可能会变得难以管理。但你可以通过在类的成员函数或成员变量中封装线程创建的逻辑来实现这一功能。

简单线程示例

以下是一个简单的示例,展示了如何在C++类的成员函数中启动一个线程:

#include <iostream>
#include <thread>
#include <chrono>

class MyClass {
public:
    MyClass() : threadPtr(nullptr) {}

    // 启动线程的成员函数
    void startThread() {
        // 检查线程是否已经在运行
        if (threadPtr == nullptr) {
            // 使用lambda表达式捕获this指针,以便在线程中访问类的成员
            threadPtr = std::make_unique<std::thread>([this]() {
                this->runInThread();
            });
        } else {
            std::cout << "Thread is already running!" << std::endl;
        }
    }

    // 线程执行的函数
    void runInThread() {
        for (int i = 0; i < 5; ++i) {
            std::cout << "Running in thread: " << i << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }

    // 等待线程完成
    void joinThread() {
        if (threadPtr != nullptr && threadPtr->joinable()) {
            threadPtr->join();
            threadPtr.reset(); // 释放线程对象
        }
    }

private:
    std::unique_ptr<std::thread> threadPtr; // 使用unique_ptr管理线程对象的生命周期
};

int main() {
    MyClass obj;
    obj.startThread(); // 启动线程

    // 让主线程等待一段时间,以便观察子线程的输出
    std::this_thread::sleep_for(std::chrono::seconds(6));

    obj.joinThread(); // 等待线程完成

    return 0;
}

在这个示例中,MyClass类有一个成员变量threadPtr,它是一个std::unique_ptr<std::thread>类型,用于管理线程对象的生命周期。startThread成员函数检查线程是否已经在运行,如果没有,则创建一个新线程来执行runInThread成员函数。joinThread成员函数用于等待线程完成并释放线程对象。注意,在捕获this指针时要小心,因为如果对象在线程执行期间被销毁,这可能会导致未定义的行为。在这个示例中,我们通过使用std::unique_ptr来确保线程对象在线程完成后被正确销毁。

线程传参

如果你需要在startThread函数中传递一些参数到线程执行的函数中,你可以通过几种方式来实现。以下是一个示例,展示了如何使用std::bind或lambda表达式来传递参数:

使用std::bind

#include <iostream>
#include <thread>
#include <chrono>
#include <functional>

class MyClass {
public:
    MyClass() : threadPtr(nullptr) {}

    // 启动线程的成员函数,接受一个int参数
    void startThread(int param) {
        // 检查线程是否已经在运行
        if (threadPtr == nullptr) {
            // 使用std::bind将参数绑定到成员函数上
            threadPtr = std::make_unique<std::thread>(std::bind(&MyClass::runInThread, this, param));
        } else {
            std::cout << "Thread is already running!" << std::endl;
        }
    }

    // 线程执行的函数,接受一个int参数
    void runInThread(int param) {
        for (int i = 0; i < 5; ++i) {
            std::cout << "Running in thread with param: " << param << ", count: " << i << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }

    // 等待线程完成
    void joinThread() {
        if (threadPtr != nullptr && threadPtr->joinable()) {
            threadPtr->join();
            threadPtr.reset(); // 释放线程对象
        }
    }

private:
    std::unique_ptr<std::thread> threadPtr; // 使用unique_ptr管理线程对象的生命周期
};

int main() {
    MyClass obj;
    obj.startThread(42); // 启动线程并传递参数42

    // 让主线程等待一段时间,以便观察子线程的输出
    std::this_thread::sleep_for(std::chrono::seconds(6));

    obj.joinThread(); // 等待线程完成

    return 0;
}

使用Lambda表达式

// ... 省略其他部分 ...

void startThread(int param) {
    // 检查线程是否已经在运行
    if (threadPtr == nullptr) {
        // 使用lambda表达式捕获this指针和param参数
        threadPtr = std::make_unique<std::thread>([this, param]() {
            this->runInThread(param);
        });
    } else {
        std::cout << "Thread is already running!" << std::endl;
    }
}

// ... 省略其他部分 ...

int main() {
    MyClass obj;
    obj.startThread(42); // 启动线程并传递参数42

    // ... 省略其他部分 ...
}

在这两个示例中,我们都修改了startThread函数以接受一个int参数,并将该参数传递给线程执行的函数runInThread。在第一个示例中,我们使用std::bind来绑定参数和成员函数,而在第二个示例中,我们使用lambda表达式来捕获参数并调用成员函数。两种方法都可以实现相同的效果。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。