【Linux】基於線程池簡單實現一個計算器

  • 基於線程池簡單實現一個計算器
#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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章