C++ thread编程(Linux系统为例)—thread成员函数与thread的创建方法

c++ 11 之后有了标准的线程库:std::thread。
参考thread库的使用

成员函数

构造函数

thread的构造函数有下面四个重载

默认构造函数

thread() noexcept

初始化构造函数

template <class Fn, class... Args>
explicit thread (Fn&& fn, Args&&... args);

该函数使用可变参数模板来构造一个线程对象,用来代表一个新的可join的执行线程。这个执行线程通过可变参数传入线程函数对象fn,以及函数的参数列表(可以简单理解为通过传值的方式将参数传给该构造函数)

拷贝构造函数

thread (const thread&) = delete;

线程不支持拷贝构造

移动构造

thread(thread&&x) noexcept;

转移参数x所代表的可执行指令的所有权,而不会影响线程的执行,转移后,参数x不再代表任何执行线程。

析构函数

析构函数用于销毁线程,如果这个线程是可以join的,那么析构函数会调用terminate()函数来终止线程。在thread对象被销毁之前应该尽可能将其join或者detach,以防止执行线程因为对象销毁而终止。

#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
void printtHelloWorld(){
    while(true){
        cout<<"hello world"<<endl;
        sleep(1);
    }
}

int main(){
    thread t1(printtHelloWorld);
    sleep(3);
    t1.~thread();
    return 0;
}

在这里插入图片描述

operator=

thread& operator= (thread&& rhs) noexcept;
thread& operator= (const thread&) = delete;

thread对象不允许拷贝构造,同样的对于赋值操作符的重载实质是移动赋值。


#include<iostream>
#include<thread>
using namespace std;
void printHelloWorld(){
    cout<<"Hello World!"<<endl;
}
int main(){
    thread t1;
    t1 = thread(printHelloWorld);
    t1.join();
    return 0;
}

编译g++ test.cpp -std=c++11 -lpthread - o test
在这里插入图片描述

joinable

如果thread对象代表了一个执行线程,那么可以joinable。
C++中有几种情况不能joinable

  • 默认构造
  • 执行过move操作
  • 执行过join或者detach
#include<iostream>
#include<thread>
using namespace std;
void printHelloWorld(){
    cout<<"Hello World!"<<endl;
}
int main(){
    thread t1;
    if(!t1.joinable()){
        cout<<"Thread is not joinable! (default constructor)"<<endl;
    }
    t1 = thread(printHelloWorld);
    if(t1.joinable()){
        cout<<"Thread is joinable! (represents a thread of execution)"<<endl;
        t1.join();
        if(!t1.joinable()){
            cout<<"Thread is not joinable! (after call join())"<<endl;
        }
    }
    thread t3;
    thread t2(printHelloWorld);
    t3 = move(t2);
    if(!t2.joinable()){
        cout<<"Thread is not joinable! (after move)"<<endl;
    }
    t3.join();
    return 0;
}

Thread is not joinable! (default constructor)
Thread is joinable! (represents a thread of execution)
Hello World!
Thread is not joinable! (after call join())
Thread is not joinable! (after move)
Hello World!

join

线程执行完毕后函数返回,join函数可以用来阻塞调用此函数的线程,调用这个函数之后,线程对象将变成非joinable并且可以被安全销毁。

#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
void pauseThread(int n){
    sleep(n);
    std::cout<<"pause of "<<n<<" seconds ended"<<std::endl;
}
int main(){
    cout<<"spawing 3 threads..."<<endl;
    std::thread t1(pauseThread,1);
    std::thread t2(pauseThread,2);
    std::thread t3(pauseThread,3);
    cout<<"Done spawning threads. Now wait for them to join: "<<endl;
    t1.join();
    t2.join();
    t3.join();
    cout<<"All threads joined!"<<endl;
    return 0;
}

在这里插入图片描述

detach

这个函数会将执行线程与调用线程分离,允许它们彼此独立运行,任意一个线程结束之后会释放拥有的资源。调用之后,线程对象会变成非joinable并且可以安全销毁。

#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
void pauseThread(int n){
    this_thread::sleep_for(chrono::seconds(n));
    std::cout<<"pause of "<<n<<" seconds ended"<<std::endl;
}
int main(){
    cout<<"spawing 3 threads..."<<endl;
    std::thread (pauseThread,1).detach();
    std::thread (pauseThread,2).detach();
    std::thread (pauseThread,3).detach();
    cout<<"Done spawning threads. (the main thread will now pause for 5 seconds)"<<endl;
    pauseThread(5);
    return 0;
}

在这里插入图片描述

创建方法

一般函数创建

#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
void printtHelloWorld(){
    while(true){
        cout<<"hello world"<<endl;
        sleep(1);
    }
}

int main(){
    thread t1(printtHelloWorld);
    sleep(3);
    t1.~thread();
    return 0;
}

类的成员函数创建

类外创建

#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
class SaySomething{
public:
    void sayHello(){
        cout<<"Hello World!\n";
    }
    void saySomething(string str){
        cout<<str;
    }
    static void sayHelloStatic(){
        cout<<"Hello static!\n";
    }
};
int main(){
    SaySomething sh;
    thread t(&SaySomething::sayHello,&sh);                      //需要传入对象的地址
    thread t1(&SaySomething::saySomething,&sh,"Hello cpp!\n");  //需要传入对象的地址和参数
    thread t2(&SaySomething::sayHelloStatic);                   //静态成员函数不需要传入对象的地址,因为静态成员函数不属于对象
    t.join();
    t1.join();
    t2.join();
    return 0;
}

在这里插入图片描述

类内创建thread对象

#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
class SaySomething{
private:
    thread workThread;
    void sayHello(){
        cout<<"Hello world!\n";
    }
public:
    SaySomething(){
        workThread=thread(&SaySomething::sayHello,this);  //需要传入对象的地址
    }
    ~SaySomething(){
        workThread.join();                                //等待线程结束,防止主线程退出时子线程被强制结束
    }
};
int main(){
    SaySomething saySomething; //Hello World!
    return 0;
}

使用函数类创建

使用函数类创建

重载operator()来实现类似于函数的操作

#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
class FunctionObject{
public:
    void operator()(string str){
        cout << str << endl;
    }
    void operator()(){
        cout << "Hello World!\n";
    }
};
int main(){
    FunctionObject fo;
    thread t(fo);                       //无参数版本
    thread t1(fo, "Hello parameter!\n");    //有参数版本
    t.join();
    t1.join();
    return 0;
}

在这里插入图片描述

lambda函数创建

#include<bits/stdc++.h>
using namespace std;
int main(){
    thread t([]{
        cout << "Hello from thread!" << endl;
    });
    t.join();
    return 0;
}

function类创建

function类实例化的对象可以包装以下任何类型的可调用对象:函数、函数指针、指向成员函数的指针或者任何类型的函数对象(即,其类定义 operator()的对象,包括闭包)

#include<iostream>
#include<thread>
#include<unistd.h>
#include<functional>
using namespace std;
void add(int a,int b){
    cout<<"Sum is: "<<a+b<<"\n";
}
int main(){
    function<void(int,int)> f=add;                          //function类包装add函数
    function<void(void)> f1 = bind(add,15,25);              //function包装一个闭包
    function<void(void)> f2 = [](){cout<<"from lambda"<<endl;};//function类包装一个lambda函数
    thread t(f,10,20); 
    sleep(1);                                     //需要传递参数,输出Sum is: 30
    thread t1(f1);      
    sleep(1);                                    //无需传参,输出Sum is: 40
    thread t2(f2);                                          //无需传参
    t.join();
    t1.join();
    t2.join();
    return 0;
}

在这里插入图片描述

bind的返回值创建

bind可以将函数和参数绑定为一个函数对象。

#include<iostream>
#include<thread>
#include<unistd.h>
#include<functional>
using namespace std;
void add(int a,int b){
    cout<<"Sum is: "<<a+b<<"\n";
}
int main(){
    auto f1 = bind(add,5,10);
    f1();                           // Sum is: 15
    auto f2 = bind(add,placeholders::_1,placeholders::_2);
    f2(10,20);                      // Sum is: 30
    thread t1(f1);
    thread t2(f2,20,30);
    t1.join();                      // Sum is: 15 来自线程的执行结果
    t2.join();                      // Sum is: 50 来自线程的执行结果
    return 0;
}

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值