【Linux】线程池

目录

Thread.hpp

LockGuard.hpp

ThreadPool.hpp

Task.hpp

main.cc


基本概念:一种线程的使用模式。线程过多会带来调度开销,进而影响局部性和整体性能。线程池维护着多个线程,等待着监督管理着分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分应用,还能防止过度调用。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量

Thread.hpp

#pragma once

#include 
#include 
#include 
#include 
#include 
#include 

namespace MyThread
{
    typedef std::function func_t;
    const int num = 1024;

    class Thread
    {
    public:
        Thread() 
        {
            char nameBuffer[num];
            snprintf(nameBuffer, sizeof(nameBuffer), "thread-%d", threadNum++);
            _name = nameBuffer;
        }

        void start(func_t func, void* args = nullptr)
        {
            _func = func;
            _args = args;
            int n = pthread_create(&_tid, nullptr, start_routine, this);
            assert(n == 0);
        }

        void join()
        {
            int n = pthread_join(_tid, nullptr);
            assert(n == 0);
        }

        std::string thread_name() {
            return _name;
        }

        void* callback()
        {
            return _func(_args);
        }

    private:
        static void* start_routine(void* args) {
            Thread* _this = static_cast(args);
            return _this->callback();
        }

    private:
        std::string _name;
        func_t _func;
        void* _args;
        pthread_t _tid;
        static int threadNum;
    };
    int Thread::threadNum = 1;  //线程编号
}

LockGuard.hpp

#pragma once

#include 
#include 

class Mutex
{
public:
    Mutex(pthread_mutex_t* plock)
    : _plock(plock)
    {}

    void lock()
    {
        if (_plock)
        {
            pthread_mutex_lock(_plock);
        }
    }

    void unlock()
    {
        if (_plock)
        {
            pthread_mutex_unlock(_plock);
        }
    }

private:
    pthread_mutex_t* _plock;
};

class LockGuard
{
public:
    LockGuard(pthread_mutex_t* mutex): _mutex(mutex)
    {
        _mutex.lock();
    }

    ~LockGuard()
    {
        _mutex.unlock();
    }

private:
    Mutex _mutex;
};

ThreadPool.hpp

#pragma once

#include "Thread.hpp"
#include "LockGuard.hpp"
#include 
#include 
#include 
#include 

using namespace MyThread;

const int g_num = 5;

template
class ThreadPool;

template
class ThreadData
{
public:
    ThreadData(ThreadPool* tp, const std::string& n)
    : threadpool(tp), name(n)
    {}

    ThreadPool* threadpool;
    std::string name;
};

template
class ThreadPool
{
public:
    void lock_queue()
    {
        pthread_mutex_lock(&_mutex);
    }

    void unlock_queue()
    {
        pthread_mutex_unlock(&_mutex);
    }

    bool is_queue_empty()
    {
        return _task.empty();
    }

    void thread_wait()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }

    T pop()
    {
        T t = _task.front();
        _task.pop();
        return t;
    }

    pthread_mutex_t* mutex()
    {
        return &_mutex;
    }

public:
    void run()
    {
        for (const auto& t: _threads)
        {
            ThreadData* td = new ThreadData(this, t->thread_name());
            t->start(handler_task, td);
            std::cout << t->thread_name() << "start ..." << std::endl;
        }
    }

    void push(const T& in)
    {
        LockGuard lockGuard(&_mutex);
        _task.push(in);
        pthread_cond_signal(&_cond);
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (const auto& t: _threads)
        {
            delete t;
        }
    }

    //单例模式
    static ThreadPool* get_instance()
    {
        if (tp == nullptr)
        {
            _singLock.lock();
            tp = new ThreadPool();
            _singLock.unlock();
        }
        return tp;
    }

private:
    static void* handler_task(void* args)
    {
        ThreadData* td = (ThreadData*)args;
        while (true)
        {
            T t;
            {
                LockGuard lockGuard(td->threadpool->mutex());
                while (td->threadpool->is_queue_empty())
                {
                    td->threadpool->thread_wait();
                }
                t = td->threadpool->pop();
            }
            std::cout << td->name << "获取一个任务:" << t.to_task_string() << " 并处理完成:" << t() << std::endl;
        }
        delete td;
        return nullptr;
    }

    ThreadPool(const int& num = g_num)
    : _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;

private:
    int _num;
    std::vector _threads;
    std::queue _task;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    
    static ThreadPool* tp;
    static std::mutex _singLock;
};

template
ThreadPool* ThreadPool::tp = nullptr;

template
std::mutex ThreadPool::_singLock;

Task.hpp

#pragma once

#include 
#include 
#include 
#include 
#include 

class Task
{
    using func_t = std::function;

public:
    Task()
    {}

    Task(int x, int y, char op, func_t func)
    : _x(x), _y(y), _op(op), _callback(func)
    {}

    std::string operator()()
    {
        int res = _callback(_x, _y, _op);
        char buffer[1024];
        snprintf(buffer, sizeof(buffer), "%d %c %d = %d", _x, _op, _y, res);
        return buffer;
    }

    std::string to_task_string()
    {
        char buffer[1024];
        snprintf(buffer, sizeof(buffer), "%d %c %d = ?", _x, _op, _y);
        return buffer;
    }

private:
    int _x, _y;
    char _op;
    func_t _callback;
};

const std::string oper = "+-*/%";

int my_math(int x, int y, char op)
{
    if (y == 0 && (op == '/' || op == '%'))
    {
        std::cerr << "div zero error!" << std::endl;
        return -1;
    }
    switch (op)
    {
    case '+':
        return x + y;
    case '-':
        return x - y;
    case '*':
        return x * y;
    case '/':
        return x / y;
    case '%':
        return x % y;
    default:
        std::cerr << "oper error!" << std::endl;
        return -1;
    }
}

main.cc

#include "ThreadPool.hpp"
#include "Task.hpp"
#include 
#include 
#include 

int main()
{
    srand((unsigned int)time(nullptr) ^ getpid());
    ThreadPool::get_instance()->run();

    while (1)
    {
        int x = rand() % 10;
        int y = rand() % 5;
        char op = oper[rand() % oper.size()];
        Task t(x, y, op, my_math);
        ThreadPool::get_instance()->push(t);
        sleep(1);
    }

    return 0;
}

你可能感兴趣的:(主线篇,Linux系统,C++,Linux,线程池,单例模式,线程)