【Linux】线程池了解

线程池:

这是对线程使用的一种使用模式,因为线程的调度会带来过渡的开销,所以线程池管理多个线程,等待分配任务,这样不仅能够保证内核的充分利用,还能防止过度的调度。(主要解决的是时间问题)

下面实现一个简单的线程池:

1、创建固定数量的线程,循环从任务队里中获取任务对象

2、获取任务对象后,执行任务对象中的任务接口

#include <iostream>
#include <queue>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>

using namespace std;

int cal(int x, int y , int op);//函数太靠后,提前声明
typedef int (*HandlerTask_t)(int x, int y, int op);//定义一个函数指针,也是任务处理的方法

class Task//任务
{
private:
    int x;
    int y;
    int op;//0:+,1:-,2:*,3:/
    HandlerTask_t handler;
public:
    Task(int x_ = -1, int y_ = -1, int op_ = -1)
        :x(x_),y(y_),op(op_)
    {
    }

    void Register(HandlerTask_t handler_)//注册的方法传进来
    {
        handler = handler_;
    }

    void Run()//处理任务
    {
        int ret = handler(x, y, op);
        const char *str = "+-*/";
        cout << "thread is [ " << pthread_self() << " ] handler result : "<<  x <<  str[op] << y << " = " << ret << endl;
    }

    ~Task()
    {
    }
};


class ThreadPool//封装一个线程池
{
private:
    int thread_nums;//线程的总数
    int idle_nums;//当前有多少个任务空闲
    queue<Task> task_queue;//得有一个任务队列,临界资源,互斥,条件变量(本身有锁)
    pthread_mutex_t lock;//互斥
    pthread_cond_t cond;//条件变量,单方面通信,一个就行

public:
    void LockQueue()//上锁
    {
        pthread_mutex_lock(&lock);
    }

    void UnLockQueue()//解锁
    {
        pthread_mutex_unlock(&lock);
    }

    bool QueueIsEmpty()
    {
        return task_queue.size() == 0 ? true : false;
    }

    void ThreadIdle()
    {
        idle_nums++;//一个线程尝试去等的时候,意味着线程池中,等待的线程数目增多
        pthread_cond_wait(&cond, &lock);
        idle_nums--;//线程醒来的时候,说明线程池中的数目就减少了
    }

    void WakeupThread()
    {
        pthread_cond_signal(&cond);
    }


    void PopTask(Task &t)
    {
        t = task_queue.front();
        task_queue.pop();
    }

public:
    ThreadPool(int num_ =5):thread_nums(num_), idle_nums(0)
    {
        pthread_mutex_init(&lock, NULL);
        pthread_cond_init(&cond, NULL);
    }

    static void *ThreadRotinue(void *arg)//线程日常事务,被疯狂的重入   成员函数默认有this指针,改成static,this就只能自己传进去
    {
        pthread_detach(pthread_self());//线程分离
        ThreadPool *tp = (ThreadPool*)arg;

        while(1)
        {
            tp->LockQueue();
            while(tp->QueueIsEmpty())//先检测有没有任务
            {
                tp->ThreadIdle();
            }
            Task t;
            tp->PopTask(t);
            //Task t = task_queue.front();
            //task_queue.pop();
            tp->UnLockQueue();//把任务拿出来,事情就完成了,怎了处理是自己的事,先把锁释放,在处理事务的时候,别人也能进来
            t.Run();
        }
    }

    void InitThreadPool()//初始化线程池
    {
        pthread_t t;
        for(int i = 0; i < thread_nums; i++)
        {
            pthread_create(&t, NULL, ThreadRotinue, this);//创建线程    上面的static让我们自己传入进去
        }
    }

    void PushTask(const Task &t)//对外暴露一个接口任务接收任务
    {
        LockQueue();
        task_queue.push(t);
        WakeupThread();
        UnLockQueue();
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
    }
};

int cal(int x, int y , int op)//模拟一个计算器
{
    int ret = -1;
    switch(op)
    {
        case 0:
            ret = x + y;
            break;
        case 1:
            ret = x - y;
            break;
        case 2:
            ret = x * y;
            break;
        case 3:
            ret = x / y;
            break;
        default:
            cout << "cal error!" << endl;
            break; 
    }
}

int main()
{
    ThreadPool tp;
    tp.InitThreadPool();
    srand((unsigned long)time(NULL));//种下一个随机数种子
    for(;;)
    {
        sleep(1);
        int x = rand() % 100 + 1;
        int y = rand() % 100 + 1;
        int op = rand() % 4;
        Task t(x, y, op);
        t.Register(cal);
        tp.PushTask(t);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值