C++版简单线程池

来源:互联网 发布:sql分组查询 编辑:程序博客网 时间:2024/04/27 16:42

需求

之前写过一个C#版本的简单线程池http://blog.csdn.net/ylbs110/article/details/51224979
由于刚刚学习了C++11新特性中的future,于是想到用它来实现一个线程池。

实现

思路基本和C#版本的一样,主要区别是委托的实现,线程句柄的不同和线程锁:

  • 本来C++有function模板,但是实现起来比较麻烦,这里主要是实现线程池,所以动态参数的委托就不实现了,直接使用typedef
    void(*Func)();来实现一个无参数无返回值的函数指针
  • 线程句柄使用future
  • 线程锁使用mutex

关于future和mutex的用法在C++标准库第2版里面讲的很清楚,这里不细说。
与C#版本的实现方式类似,首先实现一个线程句柄类,该类主要用来存储线程池中运行的方法的句柄,并且实现对该方法的关闭操作,完成状态查询,循环状态查询等一系列功能。
线程池中使用队列来存储还未运行的方法,所有线程也使用一个队列存储起来。所有线程都运行一个run方法,该方法主要用来从线程句柄队列中提取任务然后运行。而提取任务的方法中需要使用mutex线程锁来防止多个线程提取任务时的冲突。
原理很简单,上代码吧:

PublicData

公共数据文件,本程序集中仅仅实现了一个Func指针

#include "stdafx.h"typedef void(*Func)();

Thread

Thread.h

#include "stdafx.h"#include <future>#include <chrono>#include "PublicData.h"using namespace std;class Thread{public:    Thread(Func f = nullptr, int waitTime = 0, int cycleTime = -1);    void setFunc(Func f, int waitTime = 0, int cycleTime = -1);    Func getFunc();    bool cancel();    bool isCancel();    bool isDone();    void run();private:    int waitTime;    int cycleTime;    bool isCycle = false;;    bool isRunning = false;    bool iscancel = false;    bool isdone = false;    Func _func;};

Thread.cpp

#include "stdafx.h"#include "Thread.h"Thread::Thread(Func f, int waitTime, int cycleTime) :_func(f), waitTime(waitTime), cycleTime(cycleTime){    if (waitTime < 0)        waitTime = 0;    if (cycleTime <= 0)        isCycle = false;}void Thread::setFunc(Func f, int waitTime, int cycleTime){    _func = f;    this->waitTime = waitTime;    this->cycleTime = cycleTime;};Func Thread::getFunc(){    return _func;};bool Thread::cancel(){    if (isdone)        return false;    else if (iscancel)        return false;    else if (isRunning && !iscancel)        return false;    else        return iscancel = true;}bool Thread::isCancel(){    return iscancel;}bool Thread::isDone(){    return isdone;}void Thread::run(){    if (isdone)        return;    if (_func == nullptr)        return;    this_thread::sleep_for(chrono::milliseconds(waitTime));    if (iscancel)        return;    isRunning = true;    if (isCycle){        (*_func)();        this_thread::sleep_for(chrono::milliseconds(cycleTime));    }    else        (*_func)();    isdone = true;}

ThreadPool

ThreadPool.h

#pragma once#include "stdafx.h"#include <deque>#include <chrono>#include <future>#include <mutex>#include <exception>#include "PublicData.h"#include "Thread.h"using namespace std;class ThreadPool{public:    ThreadPool(int i = 1);    ~ThreadPool();    Thread create(Func f, int waitTime = -1, int cycleTime = -1);    void shoutdown();    bool isShoutdown();private:    deque<Thread> threadDeque;    deque<future<void>> futureDeque;    mutex runMutex;    int futureNum;    Func getFunc();    void run();};

ThreadPool.cpp

#include "stdafx.h"#include "ThreadPool.h"ThreadPool::ThreadPool(int i){    threadDeque = deque<Thread>();    futureDeque = deque<future<void>>();    futureNum = i;    while (i-- > 0)    {        futureDeque.push_back(async(launch::async, [this]{            //run();            while (true)            {                if (threadDeque.size() > 0){                    auto r = threadDeque.begin()->getFunc();                    threadDeque.pop_front();                    r();                }            }        }));    }};ThreadPool::~ThreadPool(){};Thread ThreadPool::create(Func f, int waitTime, int cycleTime){    threadDeque.push_back(Thread(f, waitTime, cycleTime));    return threadDeque.back();};void ThreadPool::shoutdown(){    while (futureDeque.size()>0)    {        futureDeque.begin()->~future();        futureDeque.pop_front();    }    while (threadDeque.size()>0)    {        threadDeque.begin()->cancel();        threadDeque.pop_front();    }};bool ThreadPool::isShoutdown(){    return !(futureDeque.size() > 0);};Func ThreadPool::getFunc(){    lock_guard<mutex> l(runMutex);    auto r = threadDeque.begin()->getFunc();    threadDeque.pop_front();    return r;};void ThreadPool::run(){    while (true)    {        if (threadDeque.size() > 0){            auto r = threadDeque.begin()->getFunc();            threadDeque.pop_front();            r();        }               }};

转载请注明出处:http://blog.csdn.net/ylbs110/article/details/51337530

测试

测试方法

void showA(){    for (int i = 0; i < 500; i++)        printf("a");    printf("\n");}void showB(){    for (int i = 0; i < 500; i++)        printf("b");    printf("\n");}void showC(){    for (int i = 0; i < 500; i++)        printf("c");    printf("\n");}void showD(){    for (int i = 0; i < 500; i++)        printf("d");    printf("\n");}

调用

    ThreadPool t=ThreadPool(5);    Thread a = t.create(showA);    Thread b = t.create(showB);    Thread c = t.create(showC);    Thread d = t.create(showD);    system("pause");    return 0;

运行结果

aaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccccccccccccccccccbbbbbbbbbbbbbbbbb请 按任意键继续. . . bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcccccccccccccccbbbbbbbbbbbbbbbbbbbbbbbbdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcbbccccbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

从结果可以看出,四个线程执行输出的时候没有先后顺序,运行成功。

1 0