基于指针的线程池

news2025/4/3 6:12:12

使用原线程池 当 push 和 pop的对象过大时,消耗时延过高,需优化线程池

采用 std::move()+ unique_ptr的方法,能极大的减少时延,

实际就是避免了多次拷贝,直接使用指针。

代码实现

ThreadPool

#ifndef _THREAD_TOOL_H_
#define _THREAD_TOOL_H_

#include<iostream>
#include<pthread.h>
#include<queue>
#include<ctime>
#include<cstdlib>
#include<Tools/Misc.h>
#include<deque>
#include<memory>  
#define NUM 5
using namespace std;

template<class T>
class ThreadPool
{
public:
    ThreadPool(int cap = NUM) : thread_num(cap)
    {
        pthread_mutex_init(&_lock, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    void LockQueue()
    {
        pthread_mutex_lock(&_lock);
    }

    void UnlockQueue()
    {
        pthread_mutex_unlock(&_lock);
    }

    void Wait()
    {
        pthread_cond_wait(&_cond, &_lock);
    }

    void Wake()
    {
        pthread_cond_signal(&_cond);
    }

    bool isQueueEmpty()
    {
        return _task_queue.size() == 0 ? true : false;
    }

    static void* Rountine(void *arg)
    {
        pthread_detach(pthread_self());
        ThreadPool* self = (ThreadPool*)arg;

        while (true)
        {
            self->LockQueue();
            while (self->isQueueEmpty()) //避免被虚假唤醒
            {
                self->Wait();
            }

            std::unique_ptr<T> t;
            self->Pop(t);
            self->UnlockQueue();

            // 执行任务
            t->run();
        }
    }

    void Thread_pool_init()
    {
        pthread_t tids[thread_num];

        for (int i = 0; i < thread_num; i++)
        {
            pthread_create(&tids[i], nullptr, Rountine, this);
        }
    }

    void push(std::unique_ptr<T>&& in)
    {
        LockQueue();
        _task_queue.push_back(std::move(in));  // 使用 move 将任务指针传入队列
        Wake();
        UnlockQueue();
    }

    // Pop 时返回 unique_ptr<T> 类型的任务指针
    void Pop(std::unique_ptr<T>& out)
    {
        out = std::move(_task_queue.front());
        _task_queue.pop_front();
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
    }

private:
    pthread_mutex_t _lock;
    pthread_cond_t _cond;
    deque<std::unique_ptr<T>> _task_queue;  // 存储智能指针
    int thread_num;
};

#endif

task 任务

#ifndef __TASK__H_
#define __TASK__H_
 
#include <iostream>
#include <functional>
#include <thread>
#include <chrono>



#include <iostream>
#include <utility> 

template<class T>
class Task 
{
public:
    Task() {
        executeFunc = nullptr;
    }

    Task(void(*func)(T), T data)
        : executeFunc(func), _data(std::move(data)) {}

    Task(const Task<T>& other)
        : executeFunc(other.executeFunc), _data(other._data) {}

    ~Task() = default;
    
    Task<T>& operator=(Task<T> other) 
    {  
        std::swap(executeFunc, other.executeFunc);
        std::swap(_data, other._data);
        return *this;
    }

    void run() 
    {
        if (executeFunc) 
        {
            executeFunc(_data);
        }
    }

public:
    void (*executeFunc)(T);
    T _data;
};


#endif




main.cc

#include "task.h"
#include "ThreadPool.hpp"
#include <stdio.h>
#include <random>

#define TASK_NUM 10

static void DoJob(vector<int> data)
{
    for(int i =0 ;i< data.size(); i++)
    {
        printf("data = %d ", data[i]);
    }
    printf("\n");
}

int main()
{
    
    uint16_t num_threads = std::thread::hardware_concurrency();
    printf("thread_nums %d\n", num_threads);

    std::unique_ptr<ThreadPool<Task<vector<int>>>> tp(new ThreadPool<Task<vector<int>>>(num_threads));
    tp->Thread_pool_init();

    std::vector<int> v1;
    std::random_device rd;
    std::mt19937 gen(rd());
    // 定义范围
    int min = 10;
    int max = 50;
    while(true)
    {
        // 定义均匀分布
        std::uniform_int_distribution<> dis(min, max);

        // 生成随机数
        int random_number = dis(gen);
        v1.push_back(random_number);

        if(v1.size() == TASK_NUM)
        {
            auto task = std::make_unique<Task<std::vector<int>>>(DoJob, std::move(v1));
            tp->push(std::move(task));
        }

    }


    return 0;
}

此线程池 可以极大的减少拷贝,降低时延,并根据当前硬件的核数,开启对应的线程数量。

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

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

相关文章

SpringMvc获取请求数据

基本参数 RequestMapping("save5") ResponseBody public User save5(String name, int age) {User user new User();user.setName(name);user.setAge(age);return user; } 在url中将name与age进行编写&#xff0c;通过框架可以提取url中的name与age&#xff0c;这…

大语言模型开发框架——LangChain

什么是LangChain LangChain是一个开发由语言模型驱动的应用程序的框架&#xff0c;它提供了一套工具、组件和接口&#xff0c;可以简化构建高级语言模型应用程序的过程。利用LangChain可以使应用程序具备两个能力&#xff1a; 上下文感知 将语言模型与上下文&#xff08;提示…

机器学习的一百个概念(7)独热编码

前言 本文隶属于专栏《机器学习的一百个概念》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…

从实用的角度聊聊Linux下文本编辑器VIM

本文从实用的角度聊聊Vim的常用命令。何为实用&#xff1f;我举个不实用的例子大家就明白了&#xff0c;用vim写代码。;) “vim是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富&#xff0c;在程序员中被广泛使用&#xff0c;和Emacs并列成…

佳能imageRUNNER 2206N基本参数及管理员密码

基本参数&#xff1a; 产品类型 激光数码复合机 颜色类型 黑白 涵盖功能 复印/打印/扫描 速度类型 低速 最大原稿尺寸 A3 复印/打印方式 激光静电转印方式 感光材料 OPC 显影系统 干式单组分显影 定影…

社交类 APP 设计:打造高用户粘性的界面

在当今数字化时代&#xff0c;社交类APP已成为人们日常生活中不可或缺的一部分。然而&#xff0c;随着市场竞争的加剧&#xff0c;如何通过设计提升用户粘性成为社交类APP成功的关键。本文将从设计的关键要素、用户界面优化、功能创新、个性化体验以及持续优化等方面&#xff0…

数据编排与Dagster:解锁现代数据管理的核心工具

在数据驱动的时代&#xff0c;如何高效管理复杂的数据管道、确保数据质量并实现团队协作&#xff1f;本文深入探讨数据编排的核心概念&#xff0c;解析其与传统编排器的差异&#xff0c;并聚焦开源工具Dagster如何以“资产为中心”的理念革新数据开发流程&#xff0c;助力企业构…

Jmeter的压测使用

Jmeter基础功能回顾 一、创建Jmeter脚本 1、录制新建 &#xff08;1&#xff09;适用群体&#xff1a;初学者 2、手动创建 &#xff08;1&#xff09;需要了解Jmeter的常用组件 元件&#xff1a;多个类似功能组件的容器&#xff08;类似于类&#xff09; 各元件作用 组件…

kubernetes》》k8s》》Deployment》》ClusterIP、LoadBalancer、Ingress 内部访问、外边访问

Nginx部署 K8s 集群内外访问服务的方式 节点 Kubernetes 集群中的服务器&#xff08;指单台&#xff09; 集群 Kubernetes 管理的一组服务器的集合 边界路由器 为局域网和Internet路由数据包的路由器&#xff0c;执行防火墙保护局域网络 集群网络 遵循Kubernetes网络模型实现集…

Transformer 通关秘籍8:词向量如何表示近义词?

上一节已经完成了 token 到词向量的转换。那么&#xff0c;使用转换后的词嵌入向量便可以表示 token 之间的语义了吗&#xff1f;便可以表示两个单词是否是近义词&#xff0c;是否是反义词了吗&#xff1f; 是的。 接下来先通过一个例子&#xff0c;来直观地理解一下词嵌入向…

【MVC简介-产生原因、演变历史、核心思想、组成部分、使用场景】

MVC简介 产生原因&#xff1a; MVC&#xff08;Model-View-Controller&#xff09;模式诞生于20世纪70年代&#xff0c;由Trygve Reenskaug在施乐帕克研究中心&#xff08;Xerox PARC&#xff09;为Smalltalk语言设计&#xff0c;目的是解决图形用户界面&#xff08;GUI&…

基于NebulaGraph构建省市区乡镇街道知识图谱(二)

上次我们有讲到构建知识图谱&#xff0c;但是在实际使用的时候会发现某些乡镇街道丢失的问题&#xff0c;因为VID必须全局唯一&#xff0c;覆盖导致原因&#xff0c;另外在全国大批量导入时速度非常慢&#xff0c;为此&#xff0c;我们重新优化表结构与导入语法。 1. 表及索引…

论文浅尝 | Interactive-KBQA:基于大语言模型的多轮交互KBQA(ACL2024)

转载至&#xff1a;何骏昊 开放知识图谱 原文地址&#xff1a;论文浅尝 | Interactive-KBQA&#xff1a;基于大语言模型的多轮交互KBQA&#xff08;ACL2024&#xff09; 笔记整理&#xff1a;何骏昊&#xff0c;东南大学硕士&#xff0c;研究方向为语义解析 论文链接&#xff…

linux -- php 扩展之xlswriter

xlswriter - PHP 最强性能 Excel 扩展 linux 安装 完整编译安装步骤 ## 下载wget https://pecl.php.net/get/xlswriter tar -zxvf xlswriter cd xlswriterphpize # 执行配置 ./configure # 编译 make make install ./configure 如果报错&#xff0c;就指定配置路径 …

Dockerfile文件构建镜像Anaconda+Python教程

文章目录 前言Dockerfile 核心模块解析**一、Dockerfile基础镜像选择二、系统基础配置1、时区设置2、镜像源替换 三、系统依赖安装四、复制本地文件五、指定路径六、Anaconda环境配置1、anaconda环境安装2、配置虚拟环境3、创建conda虚拟环境4、启动和安装环境 七、完整dockerf…

本地部署大模型-web界面(ollama + open-webui)

一、安装ollama 二、安装部署open-webui 1、项目运行环境 &#xff08;1&#xff09;配置python环境—官方下载链接 可通过命令行直接更改python镜像源为阿里云镜像源&#xff1a; >pip config set global.index-url http://mirrors.aliyun.com/pypi/simple/也可手动修…

Java虚拟机JVM知识点(已完结)

JVM内存模型 介绍下内存模型 根据JDK8的规范&#xff0c;我们的JVM内存模型可以拆分为&#xff1a;程序计数器、Java虚拟机栈、堆、元空间、本地方法栈&#xff0c;还有一部分叫直接内存&#xff0c;属于操作系统的本地内存&#xff0c;也是可以直接操作的。 详细解释一下 程…

【C++进阶四】vector模拟实现

目录 1.构造函数 (1)无参构造 (2)带参构造函数 (3)用迭代器构造初始化函数 (4)拷贝构造函数 2.operator= 3.operator[] 4.size() 5.capacity() 6.push_back 7.reserve 8.迭代器(vector的原生指针) 9.resize 10.pop_back 11.insert 12.erase 13.memcpy…

VUE3+Mapbox-GL 实现鼠标绘制矩形功能的详细代码和讲解

以下是如何使用 Mapbox GL JS 实现鼠标绘制矩形功能的详细代码和讲解。Mapbox GL JS 是一个强大的 JavaScript 库&#xff0c;可以用来创建交互式地图。下面将通过监听鼠标事件并动态更新地图图层来实现这一功能。 实现步骤 初始化地图 在 HTML 文件中引入 Mapbox GL JS 库&…

《筋斗云的K8s容器化迁移》

点击下面图片带您领略全新的嵌入式学习路线 &#x1f525;爆款热榜 88万阅读 1.6万收藏 文章目录 **第一章&#xff1a;斗战胜佛的延迟焦虑****第二章&#xff1a;微服务化的紧箍咒****第三章&#xff1a;混沌中的流量劫持****第四章&#xff1a;量子筋斗的终极形态****终章&…