C++ std::thread 线程创建和启动

01

 

引言

std::thread 是C++11标准引入的一个轻量级线程库,它提供了创建和管理线程的能力,方便用户创建新的线程,并执行指定的函数。

 

02

 

使用方法

std::thread 使用很方便,以下是一个简单的示例代码:

  •  
#include <iostream>#include <thread>
void myTask(int id) {    std::cout << "Thread " << id << " is running" << std::endl;}
int main() {    std::thread t1(myTask, 1);  // 创建一个新线程 t1,执行 myTask 函数,并传递参数 1    std::thread t2(myTask, 2);  // 创建一个新线程 t2,执行 myTask 函数,并传递参数 2
    std::cout << "Main Thread is running" << std::endl;
    t1.join();  // 等待线程 t1 执行完毕    t2.join();  // 等待线程 t2 执行完毕
    std::cout << "All threads are finished" << std::endl;
    return 0;}

results:

Main Thread is running

Thread 1 is running

Thread 2 is running

All threads are finished

 

 

03

 

std::thread 线程创建方法

在 C++ 中,使用标准库的 std::thread 类可以创建和管理线程。以下是创建线程的基本步骤:

  1. 定义线程函数:首先需要定义一个函数,作为线程的入口点。该函数将在新线程中执行。例如:

  •  
void myThreadFunction() {    // 在这里编写线程的逻辑代码}
  1. 创建线程对象并启动线程:使用 std::thread 类创建线程对象,并将线程函数作为参数传递给构造函数。然后,使用线程对象的 join 或 detach 方法。

  •  
int main() {    // 创建线程对象并启动线程    std::thread myThread(myThreadFunction);
    // 执行其他主线程的操作
    // 等待线程结束并回收资源    myThread.join();
    return 0;}

除了 join 方法外,还可以使用 detach 方法分离线程。使用 detach 后,线程将在后台运行,且不能再通过 join 方法等待其结束。这在某些情况下可能会有用,但需要确保线程的资源能够正确管理和释放。

 

 

04

 

std::thread 线程函数参数

在创建 std::thread 对象时,可以向其构造函数传递线程函数的参数。有几种方式可以传递参数:

  1. 使用函数指针或成员函数指针:如果线程函数是一个全局函数、静态成员函数或非静态成员函数,可以直接将函数指针或成员函数指针作为参数传递给 std::thread 构造函数。例如:

  •  
void myThreadFunction(int arg1, double arg2) {    // 在线程函数中使用传递的参数    // TODO: 线程逻辑代码}
class MyClass {public:    void myMemberThreadFunction(int arg1, double arg2) {        // 在成员线程函数中使用传递的参数        // TODO: 线程逻辑代码    }};
int main() {    int arg1 = 42;    double arg2 = 3.14;    std::thread myThread(myThreadFunction, arg1, arg2);
    MyClass obj;    std::thread memberThread(&MyClass::myMemberThreadFunction, &obj, arg1, arg2);
    // 执行其他主线程的操作
    myThread.join();    memberThread.join();
    return 0;}

2. 使用 lambda 表达式:可以使用 lambda 表达式捕获并传递参数。例如:

  •  
int main() {    int arg1 = 42;    double arg2 = 3.14;
    std::thread myThread([&arg1, arg2]() {        // 在线程函数中使用捕获的参数        // TODO: 线程逻辑代码    });
    // 执行其他主线程的操作
    myThread.join();
    return 0;}

lambda 表达式 [&arg1, arg2] 捕获了外部变量 arg1,并通过值传递方式传递了 arg2,然后将 lambda 表达式作为线程函数传递给 std::thread 构造函数。

3. 无论是使用函数指针、成员函数指针还是 lambda 表达式,都可以在创建 std::thread 对象时传递线程函数的参数。这样可以灵活地传递参数给线程函数,并在处理线程时进行更细粒度的控制。

 

 

05

 

std::thread 线程构造函数

以下是 std::thread 构造函数的几种常用形式:

  1. 默认构造函数:创建一个未关联任何线程的 std::thread 对象。

  •  
std::thread t;
  1. 函数构造函数:接受一个可调用对象(如函数、lambda表达式或函数对象)作为参数,创建并启动一个新线程。

  •  
std::thread t(threadFunction);
  1. 参数化函数构造函数:接受一个可调用对象和若干参数,这些参数将被传递给可调用对象。

  •  
std::thread t(threadFunction, arg1, arg2, ...);
  1. 复制构造函数(已删除):std::thread 的复制构造函数被删除,因此不能通过复制来复制线程对象。

  2. 移动构造函数:接受一个 std::thread 对象作为参数,转移线程所有权。

  •  
std::thread t1(threadFunction);std::thread t2 = std::move(t1);
  1. 从 std::thread::id 构造:接受一个 std::thread::id 类型的参数,但通常不直接使用。

  •  
std::thread::id id;std::thread t(id);
  1. 接受现有线程的构造函数:接受一个已经存在的 std::thread 对象,创建一个新的线程对象,两者将共享同一个线程。

  •  
std::thread t1(threadFunction);std::thread t2 = t1; // t2 现在引用 t1 的线程

 

 

06

 

std::thread 线程状态属性

在C++中,std::thread 类并没有直接提供线程状态属性,如线程是否正在运行、阻塞或已完成。然而,你可以使用一些方法来推断线程的状态或与之相关的信息:

  1. joinable()

    joinable成员函数可以用来检查线程是否可加入,即线程是否已经启动且尚未完成。如果线程已经启动且未完成,返回 true;如果线程尚未启动或已经完成,返回 false。

  •  
std::thread t(threadFunction);bool isThreadRunning = t.joinable(); // 检查线程是否可加入
  1. get_id():

    get_id成员函数返回线程的唯一标识符。如果线程未启动或已经结束,返回 std::thread::id()。

  •  
std::thread::id id = t.get_id(); // 获取线程ID
  1. join()

    调用 join() 会等待线程完成。如果线程已经完成,join() 将立即返回。

  •  
t.join(); // 等待线程t完成
  1. detach()

    调用 detach() 会分离线程,使其在后台运行。分离后的线程将无法被 join() 或 cancel()。

  •  
t.detach(); // 线程在后台继续运行
  1. 硬件线程数

    std::thread::hardware_concurrency() 函数可以用来获取系统支持的硬件线程数,这有助于确定并行任务的最佳数量。

  •  
std::thread::hardware_concurrency(); // 获取硬件线程数
  1. 自定义同步机制

    使用 std::mutex、std::condition_variable 或 std::atomic 等同步机制,可以自定义线程状态的检查和控制。

 

 

07

 

小结

​​​​​​​#include <iostream> #include <thread> using namespace std; void foo(int Z) { // 一个虚拟函数 for (int i = 0; i < Z; i++) { cout << "线程使用函数指针作为可调用参数\n"; }} class thread_obj { // 可调用对象public: void operator()(int x) { for (int i = 0; i < x; i++) cout << "线程使用函数对象作为可调用参数\n"; }}; int main() { thread th1(foo, 3); // 函数指针 thread th2(thread_obj(), 3); // 函数对象 auto f = [](int x) { // 定义 Lambda 表达式 for (int i = 0; i < x; i++) cout << "线程使用 lambda 表达式作为可调用参数\n"; }; thread th3(f, 3); // 线程通过使用 lambda 表达式作为可调用的参数 th1.join(); // 等待线程 t1 t2 t3完成 th2.join(); th3.join(); return 0;}

 

 

C++标准库中的`std::thread`是一个用于创建管理线程的类。它提供了一种简单而有效的方式来创建管理线程,并在不同的线程上执行任务。 要使用`std::thread`创建线程,需要按照以下步骤进行操作: 1. 包含头文件:在代码中包含`<thread>`头文件。 2. 定义线程函数:将要执行的代码封装在一个函数中,该函数将作为新线程要执行的代码。 3. 创建线程对象:使用`std::thread`构造函数创建一个线程对象,并将要执行的函数作为参数传递给它。 4. 启动线程:调用线程对象的`start()`成员函数来启动线程。这将使线程函数在新的线程上执行。 下面是一个简单的示例代码,展示了如何使用`std::thread`创建线程: ```cpp #include <iostream> #include <thread> // 线程函数 void myThreadFunction() { std::cout << "Hello from new thread!" << std::endl; } int main() { // 创建线程对象并启动线程 std::thread myThread(myThreadFunction); myThread.join(); // 等待新线程完成执行 return 0; } ``` 在上面的示例中,我们定义了一个名为`myThreadFunction`的函数,它将在新的线程上执行。然后,我们使用`std::thread`构造函数创建了一个名为`myThread`的线程对象,并将`myThreadFunction`函数作为参数传递给它。最后,我们调用`myThread.join()`来等待新线程完成执行。 需要注意的是,一旦线程对象被创建启动后,就不能再被重新启动或销毁。因此,在使用`std::thread`时,需要确保正确管理线程的生命周期,并在适当的时候调用`join()`或`detach()`方法来控制线程的执行终止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值