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

news2024/12/24 19:58:53

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;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/565864.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux命令(21)之usermod

Linux命令之usermod 1.usermod介绍 usermod命令用来更改/etc/passwd或/etc/shadow文件下用户属性&#xff0c;包括但不限于shell类型、用户id&#xff0c;用户gid、家目录、锁定及解锁用户等等。 2.usermod用法 usermod [参数] [用户名] usermod常用参数 参数说明-u修改UID…

淘宝/天猫商品评论数据采集

淘宝商品评论API接口是指允许开发者通过API接口获取淘宝商品的评价信息的一种技术手段。通过使用这个接口&#xff0c;开发者可以快速获取淘宝商品的评价信息&#xff0c;以实现自己的商业用途。 淘宝商品评论API接口需要开发者提供相应的数据访问权限&#xff0c;包括授权和Ap…

Linux命令(22)之chage

Linux命令之chage 1.chage介绍 usermod命令用来更改linux用户密码到期信息&#xff0c;包括密码修改间隔最短、最长日期、密码失效时间等等。 2.chage用法 chage常用参数 参数说明-m密码可更改的最小天数&#xff0c;为0表示可以随时更改-M密码有效期最大天数-W密码到期前提…

代理模式 静态代理 JDK动态代理 Cglib动态代理

1.静态代理 总共只有两个类&#xff0c;代理类和被代理类。其中代理类是被代理类的增强和扩展 被代理的类C和代理类B都要实现同一个接口 代理类B中调用代理类C中相同的方法 interface D {public void function1(); }class C implements D {Overridepublic void function1(…

PyQt5桌面应用开发(18):自定义控件界面设计与实现

本文目录 PyQt5桌面应用系列定制控件-界面设计本文目标功能分析 功能设计绘制方形图案鼠标交互事件和属性 完整代码总结 PyQt5桌面应用系列 PyQt5桌面应用开发&#xff08;1&#xff09;&#xff1a;需求分析 PyQt5桌面应用开发&#xff08;2&#xff09;&#xff1a;事件循环 …

chatgpt赋能python:PythonTile:一种强大的界面构建工具

Python Tile&#xff1a;一种强大的界面构建工具 Python Tile是一种基于Python编程语言的界面构建工具&#xff0c;其目的是帮助开发者快速创建精美的用户界面&#xff0c;从而提高应用程序的用户体验。本文将介绍Python Tile的功能和优势&#xff0c;并讨论其在实际开发中的应…

Doris数据库BE——LoadChannelMgr原理解析

数据在经过清洗过滤后&#xff0c;会通过Open/AddBatch请求分批量将数据发送给存储层的BE节点上。在一个BE上支持多个LoadJob任务同时并发写入执行。LoadChannelMgr负责管理这些任务&#xff0c;并对数据进行分发。 internal service Open/AddBatch请求接口使用BRPC&#xff…

STP 生成树协议

STP&#xff08;Spanning-Tree Protocol&#xff09;的来源 在网络三层架构中&#xff0c;我们会使用冗余这一技术&#xff0c;也就是对三层架构中的这些东西进行备份。冗余包含了设备冗余、网关冗余、线路冗余、电源冗余。 在二层交换网络中进行线路冗余&#xff0c;如图&am…

Linux :: 【基础指令篇 :: 用户管理:(2)】::设置用户密码(及本地Xshell 登录云服务器操作演示) :: passwd

前言&#xff1a;本篇是 Linux 基本操作篇章的内容&#xff01; 笔者使用的环境是基于腾讯云服务器&#xff1a;CentOS 7.6 64bit。 目录索引&#xff1a; 1. 基本语法 2. 基本用法 3. 注意点 4. 补充&#xff1a;指定用户设置密码操作实例测试及登录本地 Xshell 登录演…

Linux命令(18)之file

Linux命令之file 1.file介绍 file命令用来识别文件类型。 2.file用法 file [参数] [文件或目录] file常用参数 参数说明-L显示符号廉洁所指向文件的类别-i显示MIME类别-b显示结果时&#xff0c;不显示文件名称 3.实例 3.1显示ztj.sh文件类型 3.2显示ztj.sh文件类型(不显示…

记一次docker中的oracle连接问题

起因是客户登陆时报错TNS-12537 登陆上上服务器后&#xff0c;发现了几个特点。 1、没有oracle用户 2、数据文件的位置和spfile里面写的不一样 3、pmon进程存在&#xff0c;但是父进程ID不是1 4、配置oracle用户及环境变量&#xff0c;但是as sysdba无法登录到数据库 查看…

Linux命令(19)之userdel

Linux命令之userdel 1.userdel介绍 userdel命令用来说删除useradd命令创建的Linux账户。 useradd创建用户&#xff1a; Linux命令(15)之useradd_小黑要上天的博客-CSDN博客 2.userdel用法 userdel [参数] [用户账户名称] userdel常用参数 参数说明-r递归删除&#xff0c;…

【网络编程】协议定制+Json序列化与反序列化

目录 一、序列化与反序列化的概念 二、自定义协议设计一个网络计算器 2.1TCP协议&#xff0c;如何保证接收方收到了完整的报文呢&#xff1f; 2.2自定义协议的实现 2.3自定义协议在客户端与服务器中的实现 三、使用Json进行序列化和反序列化 3.1jsoncpp库的安装 3.2改造…

学系统集成项目管理工程师(中项)系列26_新兴信息技术

1. 云计算 1.1. 基于互联网的超级计算模式&#xff0c;通过互联网来提供大型计算能力和动态易扩展的虚拟化资源 1.2. 通过网络提供可动态伸缩的廉价计算能力 1.3. 特点 1.3.1. 【19上选23】 1.3.2. 超大规模 1.3.3. 虚拟化 1.3.4. 高可靠性 1.3.5. 通用性 1.3.6. 高可…

linux共享内存总结

共享内存函数由shmget、shmat、shmdt、shmctl四个函数组成 头文件&#xff1a; #include <sys/ipc..h> #include<sys/shm.h> // 创建或获取一个共享内存: 成功返回共享内存ID&#xff0c;失败返回-1 int shmget (key_t key, size_t_size, int flag); // 连接共享内…

Java修饰符

4 修饰符(static关键字) 4.1 权限修饰符 4.2 状态修饰符 final(最终态)static(静态)4.2.1 final的特点 final 关键字是最终的意思,可以修饰成员变量,成员方法,类final修饰的特点: 1.修饰方法:表示该方法是最终方法,不能被重写2.修饰变量:表示该变量是常量,不能被…

深入了解Nginx:高性能的开源Web服务器与反向代理

一、Nginx是什么 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器&#xff0c;也可以作为负载均衡器和HTTP缓存服务器使用。它采用事件驱动、异步非阻塞的处理方式&#xff0c;能够处理大量并发连接和高流量负载&#xff…

推荐试试这个简单好用的手机技巧

技巧一&#xff1a;一键锁屏 除了按住手机电源键进行锁屏外&#xff0c;还有其他一些快捷方法可以实现锁屏操作。 对于苹果手机用户&#xff0c;可以按照以下步骤进行设置&#xff1a; 1.打开手机的设置应用&#xff0c;通常可以在主屏幕或应用列表中找到该图标。 2.在设置…

chatgpt赋能python:Pythonunittest跳过用例:使用unittest中跳过测试用例的方法

Python unittest 跳过用例&#xff1a;使用unittest中跳过测试用例的方法 如果你正在开发一个Python项目&#xff0c;你可能已经使用了Python的unittest模块来编写并运行测试用例。在编写测试用例时&#xff0c;有些情况下你可能不想运行某些测试用例&#xff0c;这时就需要使…