基于指针的线程池

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

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

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

代码实现

ThreadPool

cpp 复制代码
#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 任务

cpp 复制代码
#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

cpp 复制代码
#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;
}

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

相关推荐
wyhwust2 小时前
No1-绪论
c++
无名猿2 小时前
C++ 对象内存模型:vtable 布局、多继承 vptr、RTTI 与 dynamic_cast 走查
c++·内存管理·调试技巧·现代c++
xuxigifxfh3 小时前
HJ15 求int型正整数在内存中存储时1的个数
java·开发语言·华为机考
Wokoo73 小时前
自动化测试入门:核心场景、回归测试与 Web 自动化环境搭建
java·开发语言·测试工具
tachibana23 小时前
Golang 中数组和切片的区别?
开发语言·后端·golang·数组·切片
All for pursuit.3 小时前
【动态规划-8】152.乘积最大子数组
数据结构·c++·算法·leetcode·动态规划
INGNIGHT3 小时前
1861 · 老鼠跳跃(坐标型dp)
数据结构·c++
Lazionr3 小时前
手撕 unordered_set 和 unordered_map,剖析哈希表底层实现
c++·算法
智购科技无人售货机工厂店3 小时前
玻璃瓶饮料破损率突然上升,排查发现是取货口缓冲垫老化了~YH
java·开发语言·人工智能·python·eclipse
枫叶丹43 小时前
语音 AI 怎样边听边答:实时对话系统的工作原理
开发语言·人工智能·chatgpt·开源·php·agent·codex