设计线程池

sudo find ../.. -name Thread.hpp

查找Thread.hpp

cp ../../20240814/mythread/Thread.hpp .

通过cp命令进行拷贝

using namespace std;
void* run(void* args)
{
    string message=(const char*)args;
    while(true)
    {
        cout<<message<<endl;
        sleep(1);
    }
    return nullptr;
}

int main()
{
    ThreadNs::Thread t1(run,(void*)"thread 1 run");
    ThreadNs::Thread t2(run,(void*)"thread 2 run");

    t1.start();
    t2.start();

    t1.join();
    t2.join();
    return 0;
}

测试线程能否成功创建的代码

线程池效果:

thread-1 start ...
thread-2 start ...
thread-3 start ...
thread-4 start ...
thread-5 start ...
请输入数据1# 1
请输入数据2# 2
请输入要进行的运算# +
thread-3获取了一个任务: 1 + 2 = ? 并处理完成,结果是: 1 + 2 = 3 
请输入数据1# ^\Quit (core dumped) 

 LockGuard.hpp

#pragma once 

#include<iostream>
#include<pthread.h>

class Mutex
{
public:
    Mutex(pthread_mutex_t* lock_p=nullptr)
        :lock_p_(lock_p)
    {}
    void lock()
    {
        if(lock_p_)
            pthread_mutex_lock(lock_p_);
    }
    void unlock()
    {
        if(lock_p_)
        {
            pthread_mutex_unlock(lock_p_);
        }
    }
    ~Mutex()
    {}
private:
    pthread_mutex_t* lock_p_;
};
//在外部将锁初始化定义好,通过LockGuard的方式保护临界资源
class LockGuard
{
public:
    LockGuard(pthread_mutex_t* mutex):mutex_(mutex)
    {
        mutex_.lock();
    }
    ~LockGuard()
    {
        mutex_.unlock();
    }
private:
    Mutex mutex_;
};

ThreadPool.hpp

//写线程池的前提是有线程
#pragma once

#include"LockGuard.hpp"
#include"Thread.hpp"
#include<vector>
#include<queue>
#include<pthread.h>
#include<unistd.h>

using namespace std;
using namespace ThreadNs;

const int gnum=5;

template<class T>
class ThreadPool;
template<class T>
class ThreadData
{
public:
    ThreadPool<T>* threadpool;
    string name;
public:
    ThreadData(ThreadPool<T>* tp,const string& in)
        :threadpool(tp),name(in)
    {}
};
template<class T>
class ThreadPool
{
private:
    static void* handlerTask(void* args)
    {
        ThreadData<T>* td=(ThreadData<T>* )args;
        while(true)
        {
            //td->threadpool->lockQueue();
            T t;
            {
                LockGuard lockguard(td->threadpool->mutex());
                while(td->threadpool->isQueueEmpty())
                {
                    td->threadpool->threadWait();
                }
                t=td->threadpool->pop();//将任务从公共队列中,拿到当前线程独立的栈结构中
            }
            
            
            //td->threadpool->unlockQueue();
            cout<<td->name<<"获取了一个任务: "<<t.toTaskString()<<"并处理完成,结果是: "<<t()<<endl;
           //实现多个任务并发处理
        }
        delete td;
        return nullptr;
    }
public:
    void lockQueue(){pthread_mutex_lock(&_mutex);}
    void unlockQueue() {pthread_mutex_unlock(&_mutex);}
    bool isQueueEmpty() {return _task_queue.empty();}
    void threadWait() {pthread_cond_wait(&_cond,&_mutex);}
    T pop()
    {
        T t=_task_queue.front();
        _task_queue.pop();
        return t;
    }
    pthread_mutex_t* mutex()
    {
        return &_mutex;
    }
public:
    ThreadPool(const int& num=gnum)
        :_num(num)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        for(int i=0;i<_num;i++)
        {
            _threads.push_back(new Thread());
        }
    }
    void run()
    {
        for(const auto& t:_threads)
        {
            ThreadData<T>* td=new ThreadData<T>(this,t->threadname());
            t->start(handlerTask,td);
            cout<<t->threadname()<<" start ..."<<endl;
        }
    }
    void push(const T& in)
    {
        //pthread_mutex_lock(&_mutex);
        LockGuard lockguard(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
        //pthread_mutex_unlock(&_mutex);
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for(const auto& t:_threads) delete t;
    }
private:
    int _num;
    vector<Thread*> _threads;
    queue<T> _task_queue;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
};

Task.hpp

#pragma once

#include<cstdio>
#include<iostream>
#include<string>
#include<functional>

using namespace std;
class Task
{
    using func_t=function<int(int,int,char)>;
    //typedef function<int(int,int)> func_t;
public:
    Task()
    {}
    Task(int x,int y,char op,func_t func):_x(x),_y(y),_op(op),_callback(func)
    {}
    string operator()()
    {
        int result=_callback(_x,_y,_op);
        //构建结构字符串
        char buffer[1024];
        snprintf(buffer,sizeof buffer,"%d %c %d = %d ",_x,_op,_y,result);
        return buffer;
    }
    string toTaskString()
    {
        char buffer[1024];
        snprintf(buffer,sizeof buffer,"%d %c %d = ? ",_x,_op,_y);
        return buffer;
    }
private:
    int _x;
    int _y;
    char _op;
    func_t _callback;
};
const string oper="+-*/";
int mymath(int x,int y,char op)
{
    int result=0;
    switch(op)
    {
        case '+':
            result=x+y;
        break;
        case '-':
            result=x-y;
        break;
        case '*':
            result=x*y;
        break;
        case '/':
        {
            if(y==0)
            {
                cerr<<"div zero error!!!"<<endl;
                result=-1;
            }
            else
                result=x/y;
        }
        break;
        case '%':
        {
            if(y==0)
            {
                cerr<<"mod zero error!!!"<<endl;
                result=-1;
            }
            else
                result=x%y;
        }          
        break;
        default:
        break;
    }
    return result;
}
class SaveTask
{
    typedef function<void(const string&)> func_t;
public:
    SaveTask()
    {}
    SaveTask(const string &message,func_t func)
    :_message(message),_func(func)
    {}
    void operator()()
    {
        _func(_message);
    }
private:
    string _message;
    func_t _func;
};
void Save(const string& message)
{
    const string target="./log.txt";
    FILE* fp=fopen(target.c_str(),"a+");
    if(!fp)
    {
        cerr<<" fopen error "<<endl;
        return;
    } 
    fputs(message.c_str(),fp);
    fputs("\n",fp);
    
    fclose(fp);
}

Thread.hpp

#pragma once

#include<cassert>
#include<iostream>
#include<string>
#include<functional>
#include<pthread.h>
using namespace std;
namespace ThreadNs
{
    typedef function<void*(void*)> func_t;
    const int num=1024;
    class Thread
    {
    private:
        //在类内创建线程,想让线程执行对应的方法,需要将方法设置为static
        static void *start_routine(void* args)//类内成员,有缺省参数!!!
        {
            Thread* _this=static_cast<Thread*>(args);
            //静态方法不能调用成员方法或者成员变量
            return _this->callback();
        }  
    public:
        //using func_t=function<void*(void*)>;
        Thread()
        {
            char buffer[num];//c99才支持用变量初始化数组
            //name_="thread-";
            //name_+=to_string(number);
            snprintf(buffer,sizeof buffer,"thread-%d",threadnum++);
            name_=buffer;
        }
        void start(func_t func,void *args=nullptr)
        {
            func_=func;
            args_=args;
            int n=pthread_create(&tid_,nullptr,start_routine,this);
        }
        void join()
        {
            int n=pthread_join(tid_,nullptr);
        }
        string threadname()
        {
            return name_;
        }
        void *callback()
        {
            return func_(args_); 
        }
    private:
        string name_;
        pthread_t tid_;
        func_t func_;//线程要执行的方法
        void *args_;//线程执行时对应的参数

        static int threadnum;
    };
    int Thread::threadnum=1;
}











 main.cc

#include"ThradPool.hpp"
#include"Thread.hpp"
#include"Task.hpp"
#include<memory>
#include<unistd.h>


using namespace std;
int main()
{
    unique_ptr<ThreadPool<Task> > tp(new ThreadPool<Task>());
    tp->run();
    int x,y;
    char op;
    while(1)
    {
        cout<<"请输入数据1# ";
        cin>>x;
        cout<<"请输入数据2# ";
        cin>>y;
        cout<<"请输入要进行的运算# ";
        cin>>op;
        Task t(x,y,op,mymath);
        tp->push(t);
        sleep(1);
    }
    return 0;
}
wc -l *
   42 LockGuard.hpp
   27 main.cc
    4 Makefile
  109 Task.hpp
   71 Thread.hpp
  118 threadpool
  114 ThreadPool.hpp
  485 total

查看代码行数

添加单例模式(懒汉模式)

ThreadPool.hpp

//写线程池的前提是有线程
#pragma once

#include"LockGuard.hpp"
#include"Thread.hpp"
#include<vector>
#include<queue>
#include<pthread.h>
#include<unistd.h>

using namespace std;
using namespace ThreadNs;

const int gnum=5;

template<class T>
class ThreadPool;
template<class T>
class ThreadData
{
public:
    ThreadPool<T>* threadpool;
    string name;
public:
    ThreadData(ThreadPool<T>* tp,const string& in)
        :threadpool(tp),name(in)
    {}
};
template<class T>
class ThreadPool
{
private:
    static void* handlerTask(void* args)
    {
        ThreadData<T>* td=(ThreadData<T>* )args;
        while(true)
        {
            //td->threadpool->lockQueue();
            T t;
            {
                LockGuard lockguard(td->threadpool->mutex());
                while(td->threadpool->isQueueEmpty())
                {
                    td->threadpool->threadWait();
                }
                t=td->threadpool->pop();//将任务从公共队列中,拿到当前线程独立的栈结构中
            }
            
            
            //td->threadpool->unlockQueue();
            cout<<td->name<<"获取了一个任务: "<<t.toTaskString()<<"并处理完成,结果是: "<<t()<<endl;
           //实现多个任务并发处理
        }
        delete td;
        return nullptr;
    }
    ThreadPool(const int& num=gnum)
        :_num(num)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        for(int i=0;i<_num;i++)
        {
            _threads.push_back(new Thread());
        }
    }
    void operator=(const ThreadPool &)=delete;
    ThreadPool(const ThreadPool &)=delete;
public:
    void lockQueue(){pthread_mutex_lock(&_mutex);}
    void unlockQueue() {pthread_mutex_unlock(&_mutex);}
    bool isQueueEmpty() {return _task_queue.empty();}
    void threadWait() {pthread_cond_wait(&_cond,&_mutex);}
    T pop()
    {
        T t=_task_queue.front();
        _task_queue.pop();
        return t;
    }
    pthread_mutex_t* mutex()
    {
        return &_mutex;
    }
public:
    
    void run()
    {
        for(const auto& t:_threads)
        {
            ThreadData<T>* td=new ThreadData<T>(this,t->threadname());
            t->start(handlerTask,td);
            cout<<t->threadname()<<" start ..."<<endl;
        }
    }
    void push(const T& in)
    {
        //pthread_mutex_lock(&_mutex);
        LockGuard lockguard(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
        //pthread_mutex_unlock(&_mutex);
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for(const auto& t:_threads) delete t;
    }
    static ThreadPool<T>* getInstance()
    {
        if(nullptr==tp)
        {
            tp=new ThreadPool<T>();
        }
        return tp;
    }
private:
    int _num;
    vector<Thread*> _threads;
    queue<T> _task_queue;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    //设计静态指针
    static ThreadPool<T>* tp;
    
};
template<class T>
ThreadPool<T>* ThreadPool<T>::tp=nullptr;

main.cc

#include"ThreadPool.hpp"
#include"Thread.hpp"
#include"Task.hpp"
#include<memory>
#include<unistd.h>


using namespace std;
int main()
{
    //unique_ptr<ThreadPool<Task> > tp(new ThreadPool<Task>());
    //tp->run();
    ThreadPool<Task>::getInstance()->run();
    int x,y;
    char op;
    while(1)
    {
        cout<<"请输入数据1# ";
        cin>>x;
        cout<<"请输入数据2# ";
        cin>>y;
        cout<<"请输入要进行的运算# ";
        cin>>op;
        Task t(x,y,op,mymath);
        //tp->push(t);
        ThreadPool<Task>::getInstance()->push(t);
        sleep(1);
    }
    return 0;
}
while :; do ps -aL | grep threadpool; sleep 1; echo "##################"; done

监视threadpool进程

    //设计静态指针
    static ThreadPool<T>* tp;//没有实例化出对象
    static mutex _singlock;
};
//只有定义了对象模版才会实例化
template<class T>//对于指针类型明确后才能赋值
ThreadPool<T>* ThreadPool<T>::tp=nullptr;
//void 不明确 void*可以设为指针
template<class T>
mutex ThreadPool<T>::_singlock;

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值