C++ 在类中创建并使用线程
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表达式来捕获参数并调用成员函数。两种方法都可以实现相同的效果。
- 点赞
- 收藏
- 关注作者
评论(0)