C++简单线程池的实现

线程池基础知识

线程池主要解决线程频繁创建销毁时资源浪费问题。

例如:
		 T1为线程创建实际
		 T2为线程运行任务时间
	  	 T3为线程销毁时间
总时间T = T1 + T2 + T3

如果T1+T3 在 T 中的总时间占比比较大,那么就可以考虑使用线程池进行优化,减少资源浪费。

线程池一般包含以下几个部分:

  • 线程列表
  • 任务队列
  • 定时器

利用c++一些新特性可以很方便的写出一个简单的线程池

c++11 thread

stl::thread 是c++ 11新加入的特性。在c++ 11 之前则是使用pthread。不过个人倒是没怎么用过pthread,学的时候就直接上的thread。pthread倒是在学校教材上比较常见。

详细可以参考std::thread

mutex 与 unique_lock

mutex中文为互斥量。对,就是那个操作系统里天天考的那个。

使用方式为上锁和解锁,不过一般使用unique_lock或者lock_guard来进行操作。
两者皆为构造时上锁,析构时解锁。利用这个特点就可以利用作用域进行解锁操作。

{
	unique_lock<mutex> lock(_lock);
	// to do
}

当to do后,离开括号作用域时,锁会被自动解锁。

condition_variable

condition_variable同样是c++ 11新加入的。中文名为条件变量。condition_variable需要配合mutex,unique_lock或者lock_gard进行使用。

详细的可以参考condition_variable

实现

参考了ThreadPool,不过说实话大佬的代码只看懂了构造和析构部分,入队操作那里依旧是云里雾里,半懂不懂。

以下是我自己的实现,同时也放到我的github上了。Tiny Http Server

// threadpool.h
#ifndef __THREADPOOL_H__
#define __THREADPOOL_H__
#include<vector>
#include<deque>
#include<mutex>
#include<condition_variable>
#include<functional>
#include<thread>
class ThreadPool{
public:
    using Function = std::function<void()>;
    ThreadPool(int maxWork);
    ~ThreadPool();
    void joinJob(Function job);   //bind封装函数参数
private:
    std::vector<std::thread> _worker;
    std::deque<Function> _jobs;
    std::mutex _lock;
    std::condition_variable _cond;
    bool _stop;
};
#endif 
//threadpool.cpp
#include "threadpool.h"
ThreadPool::ThreadPool(int maxWork):_stop(false){
    maxWork <=0 ? maxWork = 1 : maxWork;
    for(int i=0 ; i < maxWork ; ++i){
        _worker.emplace_back([this](){
            for(;;){
                Function job;
                {
                    std::unique_lock<std::mutex> lock(_lock);  //构造加锁,系构解锁 RAII
                    while(!_stop && _jobs.empty())
                        _cond.wait(lock);                   //不满足则解锁,阻塞。防止假唤醒需要while判断
                    if(_stop && _jobs.empty())
                        return;
                    job = _jobs.front();
                    _jobs.pop_front();
                }
                job();
            }
        });
    }
}
ThreadPool::~ThreadPool(){
    {
        std::unique_lock<std::mutex> lock(_lock);   //上锁
        _stop = true;
    }
    _cond.notify_all();
    for(auto &job : _worker)
        job.join();
}
void ThreadPool::joinJob(Function job){
    {
        std::unique_lock<std::mutex> lock(_lock);
        _jobs.push_back(job);
    }
    _cond.notify_one();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
线程池是一种重用线程的机制,通过管理线程的生命周期、线程的数量和任务的调度,实现高效的多线程处理。线程池的主要目的是减少线程创建和销毁的开销,提高线程的重用性和整体性能。 线程池实现可以采用依赖于具体语言和平台的不同方式。在C语言中,我们可以通过以下步骤来实现一个简单线程池: 1. 定义线程池的数据结构。可以使用结构体来存储线程池的属性,如线程数量、互斥锁、条件变量等。 2. 初始化线程池。在初始化过程中,需要初始化线程池的属性,包括线程数量、互斥锁和条件变量,并创建指定数量的线程。 3. 定义工作任务。工作任务是线程池中的每个线程需要执行的具体任务。可以定义函数指针或结构体来表示工作任务。 4. 实现线程池的调度逻辑。在调度逻辑中,需要设置线程池中每个线程的状态,以及获取任务并分发给空闲线程进行处理。 5. 实现线程池的销毁操作。在销毁操作中,需要释放线程池中的资源,包括线程、互斥锁和条件变量。 通过以上步骤,我们可以实现一个简单线程池。在实际应用中,还可以对线程池进行扩展,如设置最大线程数量、超时处理、任务队列等,以更好地满足实际需求。 线程池的优点是可以提高多线程程序的性能和效率,避免了线程创建和销毁的开销,提高了线程的重用性。同时,线程池还可以进行任务调度和管理,使得多线程的编程更加方便和可控。它可以适用于需要处理大量耗时任务的应用场景,如服务器程序和并行计算等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值