Linux之线程池(二)

设计线程池

大纲

成员变量
成员函数

先完成一个基本框架的设计

构造

由于我们调用是说我们自己设计的thread

start wait stop

和单线程那里类似

主要是让所有线程都开启上面那些函数

测试一下
以上基本功能已经实现,接下来我们对其进行改变一下

这个任务相当于是全局的,要是我们想要让他在类里面实现该又怎么做呢??

我们将任务函数变成成员函数

编译的时候发现失败了这是为什么????

普通成员函数隐含参数this,类型是 void (ThreadPool<int>::*)()不是普通函数指针 void (*)(),Thread 类构造只接收普通函数指针,编译直接报错。

那么应该如何解决???

首先我们可以先让他变成static

当然我们也可以用

直接用lambda 捕获 this传入,完美解决!

std::function<void()>可以接收:

  1. 普通全局函数
  2. lambda 表达式(可以捕获this
  3. bind 绑定成员函数

上面谈完这个问题,

接下来我们对任务进行更加细致的修改

再执行任务的时候是要进行加锁和减锁的

因为要求每个线程调用的任务是不重复的

再临界区内我们哟啊检测任务,

如果有任务该怎么办

没有任务有该怎么办

有任务,取任务就是将公共资源变成私有的

enqueue

唤醒线程的逻辑是只要有有线程处于休眠状态就进行唤醒

测试

对于stop逻辑的更新

需求:

  1. 使用_isrunning标志位控制线程池运行状态
  2. 队列中剩余任务全部执行完毕之后,工作线程才允许退出
  3. 使用Broadcast唤醒所有休眠的工作线程
  4. 线程处理函数(handler)内部判断条件,自动 break 退出循环

也就是说对于handler函数那里还需要做出调整

当任务不为空的时候,要继续执行,也就是说不能让线程休眠

当线程池要退出时,线程也不能休眠,

任意满足上面两条都是不可以进行休眠

--->那什么时候可以进行休眠呢??

当上面两条都不满足的时候

测试

cpp 复制代码
class Task
{
public:
    ~Task()
    {
    }
    Task(int x, int y)
        : _x(x),
          _y(y)
    {
    }
    void Excute()
    {
        _ret = _x + _y;
    }
    void operator()()
    {
        _ret = _x + _y;
    }
    string PrintAns()
    {
        return to_string(_x) + "+" + to_string(_y) + "=" + to_string(_ret);
    }
    string PrintQuestion()
    {
        return to_string(_x) + "+" + to_string(_y) + "=?";
    }

private:
    int _x;
    int _y;
    int _ret;
};

using task_t = function<void()>;

int main()
{
    srand(time(nullptr) ^ getpid());
    ENABLE_CONSOLESTRATEGY();
    unique_ptr<ThreadPool<Task>> pool = make_unique<ThreadPool<Task>>();
    pool->Start();
    int cnt = 10;
    while (cnt--)
    {
        int x = rand() % 10 + 1;
        int y = rand() % 20 + 1;
        Task t(x, y);
        sleep(1);
        pool->Enqueue(t);
        sleep(1);
    }
    pool->Wait();

    return 0;
}
cpp 复制代码
 void handlertask()
    {
        char buf[64];
        pthread_getname_np(pthread_self(), buf, sizeof(buf));
        while (1)
        {
            // 保护临界区
            _mutex.Lock();
            
            // 检测任务.   不休眠->1.队列不为空2.线程池退出
            while (_qu_task.empty()&&_isrunning)
            {
                // 没有任务
                _slaver_sleep_count++;
                _cond.Wait(_mutex);
                _slaver_sleep_count--;
            }

            // 有任务或者线程池退出
            //   1&&2  ---->break
            if(!_isrunning&&_qu_task.empty())
            {
                _mutex.Unlock();
                break;
            }
            // 如果模板是一个类要怎么做
            T mytask = _qu_task.front();
            _qu_task.pop();
            // 处理任务??需要在临界区内执行吗???
            // 不需要不然就成为单线程
            _mutex.Unlock();
            LOG(LogLevel::INFO) << "my  name:" << buf;
            mytask();
            LOG(LogLevel::INFO) << "my  job:" <<mytask.PrintAns();
        }
    }
相关推荐
跨境小彭6 小时前
Temu运营避坑:制造地点信息填写规范、后果及批量实操教程
大数据·运维·自动化·跨境电商·temu
Cx330❀6 小时前
【Linux网络】网络层 IP 协议:从网段划分到内核源码解析
大数据·linux·服务器·网络·tcp/ip·性能优化·langchain
企鹅的蚂蚁6 小时前
LubanCat RK3588 实时 Linux 开发(七):YT6801 PCIe 网卡驱动移植与 vermagic 排查
linux·rk3588·linux驱动·yt6801·pcie网卡·vermagic
DYWorker0016 小时前
Linux驱动子系统:DMA子系统 —— Consumer和Provider(006)
linux·驱动开发
byte轻骑兵7 小时前
【BlueZ】 log 模块:日志系统的实现与自定义日志输出配置
linux·人工智能·bluez·电脑蓝牙·嵌入式蓝牙
Dachui_11227 小时前
ZeroNews LFS 使用教程:NAS 文件发布为公网 HTTPS 文件空间,不传网盘、按人授权、免登录分享
运维·网络安全·文件共享·团队协作·nas
智能运维指南7 小时前
2026年企业自动化运维平台选型:四类架构的差异与决策逻辑
运维·人工智能·嘉为蓝鲸
探索云原生7 小时前
KubeClipper 1.7.0 发布:Operation 优化与 Kubernetes 1.37 支持
linux·docker·云原生·kubernetes·go
szephyr7 小时前
Nginx 反向代理实战:从 502、跨域到 HTTPS,一次打通
运维·nginx·https·部署·反向代理
一技安身8 小时前
【信创】docker-26.0.2.tgz 原理 + 完整安装
linux·运维·服务器