线程池:线程池的实现 | 日志

在这里插入图片描述

🌈个人主页: 南桥几晴秋
🌈C++专栏: 南桥谈C++
🌈C语言专栏: C语言学习系列
🌈Linux学习专栏: 南桥谈Linux
🌈数据结构学习专栏: 数据结构杂谈
🌈数据库学习专栏: 南桥谈MySQL
🌈Qt学习专栏: 南桥谈Qt
🌈菜鸡代码练习: 练习随想记录
🌈git学习: 南桥谈Git

🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈
本科在读菜鸡一枚,指出问题及时改正

原理

在一个可执行程序内部存在多个线程和一个任务队列。如果任务队列里长时间没有任务,这些线程就会休眠,如果此时来了一个任务,那么线程就会被唤醒。像这种,提前创建好线程,需要的时候直接使用,我们称之为线程池。这种本质上就是一个生产消费模型。
在这里插入图片描述

线程池实现

//ThreadPool.hpp
#pragma once

#include<iostream>
#include<unistd.h>
#include<string>
#include<vector>
#include<queue>
#include<functional>
#include"Thread.hpp"

using namespace threadModel;

static const int gdefaultnum=5;

void test()
{
   
   
    while(true)
    {
   
   
        std::cout<<"hello world"<<std::endl;
        sleep(1);
    }
}

template<typename T>
class ThreadPool
{
   
   
private:
    void LockQueue()
    {
   
   
        pthread_mutex_lock(&_mutex);
    }

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

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

    void WakeupAll()
    {
   
   
        pthread_cond_broadcast(&_cond);
    }

    void Sleep()
    {
   
   
        pthread_cond_wait(&_cond,&_mutex);
    }

    bool IsEmpty()
    {
   
   
        return _task_queue.empty();
    }

    void HandlerTask(const std::string& name)  // this
    {
   
   
        while (true)
        {
   
   
            LockQueue();
            //如果队列为空(有任务)
            while(IsEmpty()&&_isrunning) //线程没有任务,但是在工作,继续休眠
            {
   
   
                _sleep_thread_num++;
                Sleep();
                _sleep_thread_num--;

            }

            if(IsEmpty()&&!_isrunning) // 任务是空的,并且线程退出工作
            {
   
   
                std::cout<<name<<" quit..."<<std::endl;
                UnlockQueue();
                break;
            }

            // 队列不为空,有任务 或者 队列被唤醒
            // 取任务
            T t=_task_queue.front();
            _task_queue.pop();
            UnlockQueue();

            // 此处任务已经不在任务队列中,任务已经被拿走,处理任务和临界资源是两码事

            t(); // 处理任务,不能不用也不能在临界区中处理
            std::cout<<name<<": "<<t.result()<<std::endl;
        }
        
    }

public:
    ThreadPool(int thread_num=gdefaultnum)
        :_thread_num(thread_num)
        ,_isrunning(false) //刚开始线程没有使用
        ,_sleep_thread_num(0)
    {
   
   
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
    }

    void Init()
    {
   
   
        func_t func=std::bind(&ThreadPool::HandlerTask,this,std::placeholders::_1);
        for(int i=0;i<_thread_num;i++)
        {
   
   
            std::string threadname="thread-"+std::to_string(i+1);
            _threads.emplace_back(threadname,func);
        }
    }

    void Start()
    {
   
   
        _isrunning=true;
        for(auto& thread:_threads)
        {
   
   
            thread.Start();
        }
    }

    void Stop()
    {
   
   
        LockQueue();
        _isrunning=false;
        WakeupAll();
        UnlockQueue();
    }

    void Equeue(const T &in)
    {
   
   
        LockQueue();
        if(_isrunning)
        {
   
   
            _task_queue.push(in);
            // 如果当前有线程在等待,需要唤醒
            if(_sleep_thread_num>0)
            {
   
   
                Wakeup();
            }
        }

        UnlockQueue();
    }

    ~ThreadPool()
    {
   
   
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
private:
    int _thread_num;
    std::vector<Thread> _threads;  // 管理多个线程
    std::queue<T> _task_queue; // 任务队列
    bool _isrunning; //当前线程是否在工作
    int _sleep_thread_num;   //计数器:休眠的线程个数

    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
}<
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值