【Linux】线程池

理解线程池

简单的来说,线程池的本质就是使用空间换取时间,例如一个程序本来就需要10个字节,但是它申请内存的时候申请了20个字节,为它以后使用,这样在下次使用的时候就不需要再次申请内存了,从而牺牲了空间节省了时间。(池化技术)

线程池优点

  • 线程池避免了在处理短时间内任务的创建和销毁。
  • 线程池不仅能够保证内核充分利用,还能防止过分调度。

线程池使用场景

  • 需要大量的线程来完成任务,且需要完成的任务时间短。
  • 对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
  • 接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。

例如

像Web服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。

线程池代码实现

下面我们实现一个简单的线程池,线程池中提供了一个任务队列,以及若干个线程(多线程)。
【Linux】线程池_第1张图片

  • 线程池中,多个线程任务都是从任务当中拿
  • 线程池对外提供一个Push接口,用于让外部线程能够将任务Push到任务队列当中。

线程池内逻辑实现,这里我们锁线程共享的变量放到构造器里头直接初始化,其中,我们还是用了队列来存线程数据,如果有线程进入,我们就会将其线程的操作方法放入队列中,当运行后,我们再将其取出
ThreadPool_V2.hpp

#pragma once
#include 
#include 
#include 
#include 
#include 
#include "Task.hpp"

const static int N = 5;
template<class T>
class ThreadPool
{
public:
    ThreadPool(int num = N):_num(num),_threads(num)
    {
        pthread_mutex_init(&_lock,nullptr);
        pthread_cond_init(&_cond,nullptr);
    }

    void lockQueue()
    {
        pthread_mutex_lock(&_lock);
    }

    void unlockQueue()
    {
        pthread_mutex_unlock(&_lock);
    }

    void threadWait()
    {
        pthread_cond_wait(&_cond,&_lock);
    }

    void threadWakeup()
    {
        pthread_cond_signal(&_cond);
    }

    bool isEmpty()
    {
        return _tasks.empty();
    }

    //必须保证只有一个线程访问这里才可以这样做
    T popTask()
    {
        T t = _tasks.front();
        _tasks.pop();
        return t;
    }
    //创建线程时要执行的任务
    //类内的成员包含this指针,如果加了static就没有了
    static void* threadRoutine(void* args)
    {
        pthread_detach(pthread_self());
        ThreadPool<T>* tp = static_cast<ThreadPool<T>*>(args);
        while(1)
        {
            //检测有没有任务需要主要
            // 1.检测队列中有没有存放任务
            // 2.有:处理
            // 3.没有:等待
            // 细节:需要加锁处理
            tp->lockQueue();
            while(tp->isEmpty())
            {
                tp->threadWait();
            }
            T t = tp->popTask();//从公共区域拿到私有区域
            tp->unlockQueue();

            t();//每个线程的处理都是独立的,不用上锁

            std::cout << "thread handler done result: " << t.formatRes() << std::endl;
        }
    }

    void start()
    {
        for(int i = 0;i < _num;i++)
        {
            pthread_create(&_threads[i],nullptr,threadRoutine,this);
        }
    }

    //向线程池推送任务
    void pushTask(const T& t)
    {
        lockQueue();
        _tasks.push(t);
        threadWakeup();
        unlockQueue();
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
    }

private:
    std::vector<pthread_t> _threads;
    int _num;

    std::queue<T> _tasks;//使用stl的自动扩容特性

    pthread_mutex_t _lock;
    pthread_cond_t _cond;
};

多线程共同执行的方法为
Task.hpp

#pragma once
#include 
#include 
#include 

class Task
{
public:
    Task()
    {
    }
    Task(int x, int y, char op) : _x(x), _y(y), _op(op), _result(0), _exitCode(0)
    {
    }
    void operator()()
    {
        switch (_op)
        {
        case '+':
            _result = _x + _y;
            break;
        case '-':
            _result = _x - _y;
            break;
        case '*':
            _result = _x * _y;
            break;
        case '/':
        {
            if (_y == 0)
                _exitCode = -1;
            else
                _result = _x / _y;
        }
        break;
        case '%':
        {
            if (_y == 0)
                _exitCode = -2;
            else
                _result = _x % _y;
        }
        break;
        default:
            break;
        }

        usleep(100000);
    }
    std::string formatArg()
    {
        return std::to_string(_x) + _op + std::to_string(_y) + "= ?";
    }
    std::string formatRes()
    {
        return std::to_string(_result) + "(" + std::to_string(_exitCode) + ")";
    }
    ~Task()
    {
    }

private:
    int _x;
    int _y;
    char _op;

    int _result;
    int _exitCode;
};

主函数,用于控制多线程
main.cc

//#include "ThreadPool_V1.hpp"
#include "ThreadPool_V2.hpp"
#include "Task.hpp"
#include 

int main()
{
    std::unique_ptr<ThreadPool<Task>> tp(new ThreadPool<Task>());//创建线程池
    tp->start();
    while(1)
    {
        //充当生产者,从网络中读取数据,构建成任务,推送给线程池

        int x,y;
        char op;
        std::cout << "please Enter x>";
        std::cin >> x;
        std::cout << "please Enter y>";
        std::cin >> y;
        std::cout << "please Enter op(+-*/%)>";
        std::cin >> op;

        Task t(x,y,op);

        tp->pushTask(t);
    }
}

在这里插入图片描述

你可能感兴趣的:(Linux,linux,java,运维)