方式1:绑定普通函数(无参数/有参数)
cpp
#include <thread>
#include <iostream>
// 普通函数(无参数)
void normalFunc() {
std::cout << "普通无参函数线程\n";
}
// 普通函数(有参数)
void normalFuncWithArgs(int a, std::string b) {
std::cout << "参数:" << a << ", " << b << "\n";
}
int main() {
// 无参普通函数
std::thread t1(normalFunc);
t1.join(); // 等待线程结束
// 有参普通函数(参数按值传递,支持多参数)
std::thread t2(normalFuncWithArgs, 100, "hello");
t2.join();
return 0;
}
结果
bash
g++ test.cpp -lpthread

方式2:绑定类成员函数
cpp
#include <thread>
#include <iostream>
class MQTTManager {
public:
void connectionLoop() {
std::cout << "MQTT 连接循环(成员函数线程)\n";
}
// 带参数的成员函数
void loopWithArgs(int timeout) {
std::cout << "超时时间:" << timeout << "ms\n";
}
};
int main() {
MQTTManager mgr;
// 无参成员函数(必须传 this/实例指针)
std::thread t1(&MQTTManager::connectionLoop, &mgr);
t1.join();
// 带参数的成员函数(参数跟在 this 后)
std::thread t2(&MQTTManager::loopWithArgs, &mgr, 5000);
t2.join();
return 0;
}
结果
bash
g++ test.cpp -lpthread

方式3:绑定lambda表达式
cpp
#include <thread>
#include <iostream>
#include <string>
int main() {
std::string msg = "lambda 线程";
int num = 10;
// 捕获上下文变量(值捕获/引用捕获)
std::thread t([msg, &num]() {
num++; // 引用捕获,修改外部变量
std::cout << "lambda:" << msg << ",num=" << num << "\n";
});
t.join();
std::cout << "外部 num=" << num << "\n"; // 输出 11
return 0;
}
结果
bash
g++ test.cpp -lpthread
结果

方式4:绑定函数对象(仿函数)
cpp
#include <thread>
#include <iostream>
// 函数对象(重载()运算符)
class ThreadFunc {
public:
void operator()(int x) {
std::cout << "函数对象:x=" << x << "\n";
}
};
int main() {
// 注意:避免最令人头疼的解析(加括号或用统一初始化)
std::thread t(ThreadFunc(), 20);
// 或 std::thread t{ThreadFunc(), 20};
t.join();
return 0;
}
结果
bash
g++ test.cpp -lpthread

方式5:分离线程(detach)
cpp
#include <thread>
#include <iostream>
#include <chrono>
void detachFunc() {
for (int i = 0; i < 3; i++) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "分离线程运行中...\n";
}
}
int main() {
std::thread t(detachFunc);
t.detach(); // 分离线程
std::cout << "主线程等待 2 秒...\n";
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "主线程退出\n";
// 分离线程还没跑完 3 次,但主线程退出,线程被终止
return 0;
}
结果
bash
g++ test.cpp -lpthread

方式6:分离线程(加锁)
cpp
#include <atomic>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>
class MyClass {
public:
MyClass() = default;
MyClass(const MyClass &) = delete;
MyClass &operator=(const MyClass &) = delete;
void function1() {
// 加锁
std::lock_guard<std::mutex> lock(mt);
std::cout << "this is function1......" << std::endl;
}
void function2(int num, std::string str) {
// 加锁
std::lock_guard<std::mutex> lock(mt);
std::cout << "this is function2......"
<< "num = " << num << ", str = " << str << std::endl;
}
void test() {
if (t1.joinable()) {
t1.join();
}
t1 = std::thread(&MyClass::function1, this);
}
void tes2(int num, std::string str) {
if (t2.joinable()) {
t2.join();
}
t2 = std::thread(&MyClass::function2, this, num, str);
}
~MyClass() {
std::cout << "this is ~MyClass ......" << std::endl;
if (t1.joinable()) {
std::cout << "this is ~t1 ......" << std::endl;
t1.join();
}
if (t2.joinable()) {
std::cout << "this is ~t2 ......" << std::endl;
t2.join();
}
}
private:
std::thread t1;
std::thread t2;
std::mutex mt;
};
int main() {
MyClass myClass;
myClass.test();
myClass.tes2(10, "hello");
return 0;
}
结果
bash
g++ test.cpp -lpthread

方式7:分离线程(持续运行)
cpp
#include <atomic>
#include <chrono>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>
class MyClass {
public:
MyClass() = default;
MyClass(const MyClass &) = delete;
MyClass &operator=(const MyClass &) = delete;
// 开始
void start() { isRunnig = true; }
// 结束
void stop() {
isRunnig = false;
if (t1.joinable()) {
t1.join();
}
if (t2.joinable()) {
t2.join();
}
}
void function1() {
while (isRunnig) {
{
std::lock_guard<std::mutex> lock(mt);
std::cout << "this is function1......" << std::endl;
}
// 模拟任务耗时
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
// 退出时打印日志
std::lock_guard<std::mutex> lock(mt);
std::cout << "function1 exit......" << std::endl;
}
void function2(int num, std::string str) {
while (isRunnig) {
{
std::lock_guard<std::mutex> lock(mt);
std::cout << "this is function2......"
<< "num = " << num << ", str = " << str << std::endl;
}
// 模拟任务耗时
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
// 退出时打印日志
std::lock_guard<std::mutex> lock(mt);
std::cout << "function2 exit......" << std::endl;
}
void test() {
if (t1.joinable()) {
t1.join();
}
// 启动function1的循环线程
t1 = std::thread(&MyClass::function1, this);
}
void tes2(int num, std::string str) {
if (t2.joinable()) {
t2.join();
}
// 启动function2的循环线程
t2 = std::thread(&MyClass::function2, this, num, str);
}
~MyClass() {
std::cout << "this is ~MyClass ......" << std::endl;
stop();
}
private:
std::thread t1;
std::thread t2;
std::mutex mt;
std::atomic<bool> isRunnig{false};
};
int main() {
MyClass myClass;
myClass.start();
myClass.test();
myClass.tes2(10, "hello");
std::this_thread::sleep_for(std::chrono::seconds(5));
myClass.stop();
return 0;
}
结果
bash
g++ test.cpp -lpthread
join和detach的区别
- join ():"等待线程干完活再走"
-
行为 :调用
join()的线程(比如主线程)会暂停执行,直到目标线程的入口函数执行完毕; -
资源:目标线程结束后,其系统资源(栈、内核线程结构体)会被立即回收,线程对象变为 "非可连接" 状态;
-
核心特点 :同步阻塞,主线程与子线程强关联,子线程必须执行完,主线程才能继续。
- detach ():"线程你自己干,我不管了"
-
行为 :调用
detach()后,线程对象与实际执行的线程解绑,子线程变为 "后台线程"(类似 Linux 的守护进程); -
资源:子线程的资源由操作系统在其执行完毕后自动回收,主线程无法感知也无法控制;
-
核心特点 :异步非阻塞 ,主线程与子线程无关联,主线程退出时,子线程会被操作系统强制终止(即使没执行完)。
| 选 join () 的场景 | 选 detach () 的场景 |
|---|---|
| 需要等待子线程执行完成(依赖其结果 / 状态) | 子线程是 "后台任务"(如日志收集、心跳检测),无需等待结果 |
| 子线程访问主线程 / 类的资源(如成员变量) | 子线程不依赖主线程资源,且生命周期与程序一致 |
| 程序退出前必须完成子线程任务(如文件写入) | 子线程可随时被终止(如临时的监控任务) |
