【Linux】23. 线程封装

news2024/12/22 14:15:20

如何理解C++11中的多线程(了解)

#include <iostream>
#include <unistd.h>
#include <thread>

void thread_run()
{
    while (true)
    {
        std::cout << "我是新线程..." << std::endl;
        sleep(1);
    }
}
int main()
{
    // 任何语言需要在Linux上实现多线程,必定是要用到pthread库的!
    // 如何看待C++11中的多线程呢?
    // 本质上就是对pthread库的封装
    std::thread t1(thread_run);

    while (true)
    {
        std::cout << "我是主线程..." << std::endl;
        sleep(1);
    }

    t1.join();

    return 0;
}

在这里插入图片描述

封装代码

封装代码写在Thread.hpp 文件当中,未来想使用封装好的线程就直接包含Thread.hpp文件即可!

// hpp 表示header only 开源代码
// 将函数定义和声明放在一起

#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>
#include <cassert>

// 先声明 要使用
class Thread;

// 上下文,当大号结构体使用
// 用Context来处理静态方法调用不了成员变量的问题
class Context
{
public:
    Thread *this_;
    void *args_;

public:
    Context() : this_(nullptr), args_(nullptr)
    {}
    ~Context()
    {}
};

// 对线程做封装,以后就不需要总去调用原生库的接口了
class Thread
{
public:
    // using func_t = std::function<void*(void*)>; -- C++11 智能指针
    typedef std::function<void *(void *)> func_t;
    const int num = 1024;

    // "void *(Thread::*)(void *args)" 类型的实参与 "void *(*)(void *)" 类型的形参不兼容C/C++(167) -- 报错
    // 为啥呢? -- 因为start_routine是类内的成员函数,有缺省参数this指针
    // void* start_routine(void* args)
    // {
    //     return func_(args);
    // }

    // 在类内创建线程  这样就没有this指针了
    static void *start_routine(void *args)
    {
        // 但是没有this指针
        // 静态方法不能调用成员方法或成员变量
        // return func_(args);
        // 可以采用友元,或者public成员的方式 这里不用!!
        
        // 将args强转成Context的指针
        Context *ctx = static_cast<Context*>(args);
        // 调用run方法 -- 将方法从静态中剥离出来
        void* ret = ctx->this_->run(ctx->args_);
        delete ctx;
        return ret;
    }

    // 构造函数
    Thread(func_t func, void *args = nullptr, int number = 0) : func_(func), args_(args)
    {
        char buffer[num];
        snprintf(buffer, sizeof buffer, "thread-%d", number);
        name_ = buffer;

        // 加上Context
        Context* ctx = new Context();
        ctx->this_ = this;
        ctx->args_ = args_;
        // 将ctx传过去
        int n = pthread_create(&tid_, nullptr, start_routine, ctx);
        //int n = pthread_create(&tid_, nullptr, start_routine, args);
        assert(n == 0);
        (void)n;
    }

    // 线程等待
    void join()
    {
        int n = pthread_join(tid_, nullptr);
        assert(n == 0);
        (void)n;
    }

    void *run(void *args)
    {
        return func_(args);
    }

    // 析构
    ~Thread()
    {
        // do nothing
    }

private:
    // 自定义线程名 方便观察(不需要通过观察tid)
    // 末尾加_ 将成员变量和参数做区分
    std::string name_;
    pthread_t tid_;
    // 线程执行任务
    func_t func_;
    // 获取参数
    void *args_;
};

使用封装

#include "Thread.hpp"
#include <memory>
#include <unistd.h>

void *thread_run(void *args)
{
    std::string work_type = static_cast<const char *>(args);
    while (true)
    {
        std::cout << "我是一个新线程,我正在做:" << work_type << std::endl;
        sleep(1);
    }
}

int main()
{
    std::unique_ptr<Thread> thread1(new Thread(thread_run, (void *)"hellothread", 1));
    std::unique_ptr<Thread> thread2(new Thread(thread_run, (void *)"countthread", 2));
    std::unique_ptr<Thread> thread3(new Thread(thread_run, (void *)"printthread", 3));
    std::unique_ptr<Thread> thread4(new Thread(thread_run, (void *)"iothread", 4));

    thread1->join();
    thread2->join();
    thread3->join();
    thread4->join();
    return 0;
}

在这里插入图片描述

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

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

相关文章

【Pandas】深入解析`pd.to_sql()`函数

【Pandas】深入解析pd.to_sql()函数 &#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1…

【香橙派 AIpro】OrangePi AIpro :教育、机器人、无人机领域的超级AI大脑,华为昇腾处理器驱动的AI开发板新标杆

【OrangePi AIpro&#xff1a;教育、机器人、无人机领域的超级AI大脑&#xff0c;华为昇腾处理器驱动的AI开发板新标杆】 文章目录 一、开箱与初印象1. 初印象2. 上手开机3. 安装和运行 TightVNC 远程桌面3.1. 安装 TightVNC 服务器3.2. 启动 VNC 服务器3.3. 在 Windows 上使用…

RTT UART设备框架学习

UART简介 UART&#xff08;Universal Asynchronous Receiver/Transmitter&#xff09;通用异步收发传输器&#xff0c;UART 作为异步串口通信协议的一种&#xff0c;工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。 UART串…

免费,Python蓝桥杯等级考试真题--第12级(含答案解析和代码)

Python蓝桥杯等级考试真题–第12级 一、 选择题 答案&#xff1a;B 解析&#xff1a;【0:4】表示取值【1,2,3,4,5】&#xff0c;故答案为B。 答案&#xff1a;B 解析&#xff1a;del lis【2】表示删除列表的元素5&#xff0c;故答案为B。 答案&#xff1a;C 解析&#xff1a;…

基础—SQL—DML(数据操作语言)插入数据

一、介绍 分类全称说明DMLData Manipulation Language数据操作语言。用来对数据库表中的数据进行增删改(插入、删除、修改) 则增、删、改是三个操作也就对应着三个关键字&#xff0c;分别是&#xff1a; 添加数据&#xff1a;&#xff08; INSERT &#xff09;修改数据&#…

数据结构与算法之线性表01

数组是一种线性数据结构&#xff0c;把相同数据类型的元素存储在连续的内存空间中&#xff0c;数组的索引&#xff08;元素在数组中的位置&#xff09;从0开始。 一、常用操作&#xff1a; 1、初始化 # 给定初始值 arr:list[int] [0] * 5 nums:list[int] [1, 2, 3, 4, 5] …

企业微信hook接口协议,ipad协议http,已读消息

已读消息 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信send_userid是long要发送的人idisRoom是bool是否是群消息 请求示例 {"uuid":"1753cdff-0501-42fe-bb5a-2a4b9629f7fb","send_userid":788130255…

旋转矩阵00

题目链接 旋转矩阵 题目描述 注意点 将图像旋转 90 度不占用额外内存空间 解答思路 需要找到将图像旋转90度的规律&#xff0c;为了不占用额外内存空间&#xff0c;可以先将图像上下翻转&#xff0c;然后再将图像沿着主对角线进行翻转&#xff0c;得到的就是旋转90度之后的…

职业探索--运维体系-SRE岗位/CRE岗位/运维岗位-服务心态-运维职业发展方向-运维对象和运维场景

参考来源&#xff1a; 极客时间专栏&#xff1a;赵成的运维体系管理课 极客时间专栏&#xff1a;全栈工程师修炼指南 赵成大佬在鹏讯云社区的文章&#xff08;77篇&#xff09; 有了CMDB&#xff0c;为什么还要应用配置管理 故障没有根因&#xff0c;别再找了 如何理解CMDB的套…

基础—SQL—图形化界面工具的DataGrip使用(2)

一、回顾与引言 &#xff08;1&#xff09; 上次内容&#xff0c;博客讲到了DDL语句的数据库操作、表操作、表字段的操作的相关语法&#xff0c;然而之前都是在MySQL的命令行当中去操作演示的。这种方式可以用&#xff0c;但是使用的话&#xff0c;第一&#xff0c;在我们日常…

JVM 内存布局深度解析,你所不知道的一面

作为Java开发者&#xff0c;想要写出高质量的代码&#xff0c;理解JVM的内存结构是必修课。本文将为您深度解析 Java 虚拟机(JVM)中的内存布局及其细节分析&#xff0c;让你在内存管理的道路上行稳致远。希望通过本文能让你彻底理解其中的奥秘。 一、内存布局概览 在我们深入具…

使用EMQX搭建MQTT服务

简介&#xff1a;EMQX 是一款开源的大规模分布式 MQTT 消息服务器&#xff0c;功能丰富&#xff0c;专为物联网和实时通信应用而设计。EMQX 5.0 单集群支持 MQTT 并发连接数高达 1 亿条&#xff0c;单服务器的传输与处理吞吐量可达每秒百万级 MQTT 消息&#xff0c;同时保证毫秒…

计算属性与监听属性

【 1 】计算属性 计算属性大致就是这样 # 1 计算属性是基于它们的依赖进行缓存的# 2 计算属性只有在它的相关依赖发生改变时才会重新求值# 3 计算属性就像Python中的property&#xff0c;可以把方法/函数伪装成属性 # 计算属性本质上是一个函数&#xff0c;它们可以通过 get…

国内市场有哪些创意交互性强,重视用户体验的APP/小程序?

在当前互联网时代&#xff0c;随着人口红利的逐渐消退&#xff0c;我们已进入存量用户竞争阶段&#xff0c;用户体验变得尤为关键。优联前端凭借十余年的前端行业经验&#xff0c;始终致力于运用前沿的前端技术、专业的交互设计和细腻的动画视效&#xff0c;为客户提供卓越的用…

LED屏控制卡是如何控制LED屏的?

LED屏控制卡是LED显示屏的关键组件之一&#xff0c;负责将输入的画面信息转换为LED屏能够显示的数据和控制信号。以下是LED屏控制卡的工作原理和功能的详细介绍&#xff1a; 1. LED显示屏控制器概述&#xff1a; LED显示屏控制器是LED显示屏的核心部件之一&#xff0c;也称为LE…

提升PostgreSQL性能的小技巧

提升PostgreSQL性能的技巧可以从多个方面入手&#xff0c;包括硬件配置、数据库配置、查询优化和索引管理。以下是一些实用的技巧&#xff1a; 1. 硬件配置 内存: 增加服务器内存&#xff0c;使更多的数据可以被缓存。 磁盘: 使用SSD硬盘提高读写速度。 CPU: 使用多核CPU&…

华为昇腾310B初体验,OrangePi AIpro开发板使用测评

0、写在前面 很高兴收到官方的OrangePi AIpro开发板测试邀请&#xff0c;在过去的几年中&#xff0c;我在自己的博客写了一系列有关搭载嵌入式Linux系统的SBC&#xff08;单板计算机&#xff09;的博文&#xff0c;包括树莓派4系列、2K1000龙芯教育派、Radxa Rock5B、BeagleBo…

智能电表的演进:提升能源管理的效率与可持续性

近年来&#xff0c;随着智能电表的迅速普及&#xff0c;能源行业经历了重大变革。这些创新设备彻底改变了能源的消费、监测和管理方式&#xff0c;提供了前所未有的精确度、实时数据分析以及对能耗的增强控制。智能电表制造商一直处在这一演进的前沿&#xff0c;不断开发和改进…

智能财务分析软件怎么样?看奥威BI现身说法

随着大数据时代的到来&#xff0c;财务分析已不再是简单的数据汇总和报表制作&#xff0c;而是需要运用先进的智能技术&#xff0c;对数据进行深度挖掘和智能分析&#xff0c;以提供有价值的决策支持。在这一背景下&#xff0c;BI智能财务分析软件应运而生&#xff0c;其中奥威…

mars3d实现geojson文件xxx.json格式等实现贴地效果

说明&#xff1a; 1.mars3d.js我们的这个sdk内部参数clampToGround是异步计算贴地效果的&#xff0c;最好的贴地方式是&#xff0c;给json数据准确的带高度的经纬度值。 补充前置知识说明&#xff0c;本身的geojson数据格式每个字段代表的意思需要掌握&#xff0c; GeoJSON …