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