最近看了些多线程方面的东西,感觉设计一个多线程池其实难度并不是很大,于是自己私下写了个简单的线程池,这个线程池只是实现了一些简单的功能,并没有涉及到线程同步方面的东西,这部分内容,我会持续更新,不断来优化这个线程池,先来看看代码吧,代码如下:
#ifndef __THREAD__H
#define __THREAD__H
#include <pthread.h>
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <vector>
#include <boost/function.hpp>
#include <boost/bind.hpp>
enum threadState
{
THREAD_NORMAL,
THREAD_BUSY,
THREAD_KILL
};
class Thread
{
typedef boost::function<void()> threadfun;
public:
Thread(const threadfun& funs,const std::string threadName = std::string()):fun(funs),threadName(threadName
{
threadHandle = -1;
state = THREAD_NORMAL;
}
~Thread(){}
void setThreadFun(const threadfun& fun)
{
this->fun = fun;
}
void run();
void stop();
private:
static void* start(void* arg)
{
Thread* thd = static_cast<Thread*>(arg);
printf("%s:",thd->threadName.c_str());
thd->fun();
return NULL;
}
public:
pthread_t threadHandle;
threadfun fun;
std::string threadName;
threadState state;
};
class ThreadPool
{
public:
ThreadPool(const int threadNum):threadNum(threadNum)
{
threadPool.clear();
}
~ThreadPool()
{
}
void addThread(const int threadNum,boost::function<void()>& f);
void delThread(const int threadNum);
void schedule();
void startAll();
void stopAll();
Thread* assignThread();
private:
int threadNum;
std::vector<Thread*> threadPool;
};
#endif
在线程类中,我们主要是通过boost::function机制来为线程对象指定相应的回调函数,而线程池则是通过使用threadpool来管理创建的线程,想必其他的内容通过名字就知道其含义了,下面来看看具体的实现吧,代码如下:
#include "Thread.h"
void Thread::run()
{
pthread_create(&threadHandle,NULL,&start,this);
}
void Thread::stop()
{
pthread_join(threadHandle,NULL);
}
void ThreadPool::addThread(const int threadNum,boost::function<void()>& f)
{
std::string threadName = "Thread";
Thread* thread = NULL;
for(int i = 0;i<threadNum;i++)
{
char buf[10];
memset(buf,0,sizeof(buf));
sprintf(buf,"%d",i);
thread = new Thread(f,threadName+buf);
assert(thread);
threadPool.push_back(thread);
}
}
void ThreadPool::delThread(const int threadNum)
{
int size = (threadPool.size() > threadNum)? threadNum : threadPool.size();
for(int i=0;i<size;i++)
{
if(threadPool[i] == NULL)
continue;
threadPool[i]->stop();
delete threadPool[i];
threadPool[i] = NULL;
}
}
void ThreadPool::startAll()
{
for(int i = 0;i<threadPool.size();i++)
{
if(threadPool[i] == NULL)
continue;
threadPool[i]->state = THREAD_BUSY;
threadPool[i]->run();
}
}
void ThreadPool::stopAll()
{
for(int i = 0; i< threadPool.size();i++)
{
if(threadPool[i] == NULL)
continue;
threadPool[i]->state = THREAD_NORMAL;
}
}
void ThreadPool::schedule()
{
for(int i = 0;i<threadPool.size();i++)
{
if(threadPool[i] == NULL || threadPool[i]->state == THREAD_BUSY)
continue;
threadPool[i]->state = THREAD_BUSY;
threadPool[i]->run();
break;
}
}
Thread* ThreadPool::assignThread()
{
for(int i = 0; i<threadPool.size();i++)
{
if(threadPool[i] == NULL || threadPool[i]->state == THREAD_BUSY)
continue;
return threadPool[i];
}
return NULL;
}
接下来,我们再来看看相关的测试用例吧,代码如下:
#include "Thread.h"
void worker()
{
printf("this is not arguments\n");
//sleep(1);
}
void worker(int a,int b)
{
int sum = a+b;
printf("this is two arguments,sum=%d\n",sum);
sleep(1);
}
void worker(int a,int b, int c)
{
int sum = a+b+c;
printf("this is three arguments,sum=%d\n",sum);
}
int main()
{
int threadNum = 10;
boost::function<void()> f = boost::bind(&worker);
ThreadPool threadPool(10);
threadPool.addThread(threadNum,f);
threadPool.startAll();
threadPool.stopAll();
//threadPool.schedule();
sleep(1);
Thread* thread = threadPool.assignThread();
assert(thread);
int a,b;
a = b = 3;
boost::function<void()> f1 = boost::bind(&worker,a,b);
thread->setThreadFun(f1);
thread->run();
sleep(1);
int c = 4;
boost::function<void()> f2 = boost::bind(&worker,a,b,c);
thread = threadPool.assignThread();
assert(thread);
thread->setThreadFun(f2);
thread->run();
sleep(5);
threadPool.delThread(threadNum);
return 0;
}
我们可以自己来指定相关的回调函数给我们的线程,然后通过调用run函数来执行,实现方式很简单,有些内容完全可以优化,例如将指定的回调函数实现为对象的方式,这样的话,可以通过为线程指定任务的方式来处理,这样就能更加灵活,方便,这部分优化我将会放在下篇博文中,在此就不多说了,代码很基础,思想很简单,先看看吧,呵呵,多谢了。
总结
这篇博文主要是在工作中涉及到的多线程,而私下想的东西,内容很简单,一个真正实用的多线程池要比这个复杂很多,但是思想应该是相通的,在后面的博文中,我会对这个线程池进行优化,也希望能够设计出一个很实用的线程池,有时候重复造轮子其实也是提高自己专业技能的一条捷径。
如果需要,请注明转载,多谢了