C++ 线程池的简易实现

首先,先简单介绍,线程池的工作原理。

1.他自身拥有一定数量的线程数组 threads,处于等待状态,等待唤醒(通过条件变量)

2.拥有一个任务队列 m_tasks,存储用户的任务,有新任务以后,唤醒线程,取出任务,通过回调函数的方式调用任务,执行完以后继续等待。

使用情况:线程池,适用于会话简短的情况下,http访问可以使用线程池,如需要长时间保持通讯的,如会话,就不要用线程池了。

本例子,采用单例模式,线程安全。

公开接口两个:

static CMyThreadPool * getInstance();
bool start(Task fun);

用户的函数 fun 的参数,可通过,bind来传递,不过要注意,如果传的是指针,需要注意他的生存周期,如果传的是 new,处理完以后,要自己 delete.

void showTicket(mutex* m){
            lock_guard<std::mutex> l(*m);
            cout <<" show ticket: " << ticket++ << endl;

}

pool->start(bind(showTicket, m));

头文件:

//定义一个函数对象类型typedef std::function<void()> Task;

class CMyThreadPool
{
private:
    int max_thread;                // max thread;
    int max_task;                // max task;
    // thread array:
    vector<thread> threads;
    // task queue:
    queue<Task> m_tasks;
    // lock:
    mutex m_lock;
    // condition:
    condition_variable has_task;
    bool running_flag;
public:
    ~CMyThreadPool(void);  //获取线程池对象指针
     static CMyThreadPool * getInstance();  //添加任务,成功返回true,失败返回false
     bool start(Task fun);
private:
    CMyThreadPool(void);
    bool InitThread();
    void DestroyPool();  //工作线程
    void WorkFun();
    static CMyThreadPool * m_pool;
    static std::mutex *singal_mutex;
};

实现:

#include "MyThreadPool.h"

CMyThreadPool * CMyThreadPool::m_pool = NULL;
mutex* CMyThreadPool::singal_mutex = new mutex();

CMyThreadPool::CMyThreadPool(void):max_thread(default_max_thread),
    max_task(default_max_task),running_flag(true)
{
}

CMyThreadPool::~CMyThreadPool(void)
{
    DestroyPool();
}

CMyThreadPool * CMyThreadPool::getInstance()
{
    if( NULL == m_pool){
        //lock();
        std::lock_guard<std::mutex> l(*singal_mutex);
        if( NULL == m_pool){
            m_pool = new CMyThreadPool();
        }
        //unlock();
    }
    return m_pool;
}

bool CMyThreadPool::start( Task fun )
{
    //判断是否第一次,延缓线程初始化
    {
        if( threads.size() == 0){
            unique_lock<mutex> l(m_lock);
            if( threads.size() == 0){
                //初始化线程
                if(!InitThread()){
                    return false;
                }
            }
        }
    }
    //判断工作队列是否已满,没满则加入工作队列
    {
        unique_lock<mutex> l(m_lock);
        if( (unsigned int)max_task > m_tasks.size()){
            m_tasks.push(fun);
        }else{
            return false;
        }
    }
    //唤醒一个线程
    has_task.notify_one();
    return true;
}

//已经上着锁了
bool CMyThreadPool::InitThread()
{
    for (int i = 0; i != max_thread; i++){
        threads.push_back(thread(&CMyThreadPool::WorkFun, this));
    }
    return true;
}

void CMyThreadPool::WorkFun()
{
    while(running_flag || !m_tasks.empty()){
        Task t;
        //获取task
        {
            unique_lock<mutex> l(m_lock);
            while( m_tasks.empty())
                has_task.wait(l);
            t = m_tasks.front();
            m_tasks.pop();
        }
        //执行task
        t();
    }
}

void CMyThreadPool::DestroyPool()
{
    {
        unique_lock<mutex> u_lock(m_lock);
        running_flag = false;
    }
    has_task.notify_all();

    for( auto &t : threads){
        t.join();
    }
    threads.clear();
}

测试用例:

#include <iostream>
#include "MyThreadPool.h"
#include <memory>
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <Windows.h>

using namespace std;
int ticket = 0;

void showTicket(mutex* m){
            lock_guard<std::mutex> l(*m);
#ifdef WIN32
            //打印当前线程号
            cout << "Thread id: " << GetCurrentThreadId();

#endif
            cout <<" show ticket: " << ticket++ << endl;

}

int main(){
    mutex *m = new mutex;
    int sum = 0;
    {
    std::shared_ptr<CMyThreadPool> pool(CMyThreadPool::getInstance());
    for(int i = 0; i < 100;i++){
        if(!pool->start(bind(showTicket, m))){
            sum++;
        }
    }
    }
    cout << "not use task : "<< sum << endl;
    delete m;
    _CrtDumpMemoryLeaks();
    system("pause");
    return 0;
}
时间: 2024-11-01 10:27:25

C++ 线程池的简易实现的相关文章

Linux下简易线程池

线程池简介 简易线程池实现 线程池头文件threadpool.h如下: 1 #ifndef THREADPOOL_H 2 #define THREADPOOL_H 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <unistd.h> 7 #include <pthread.h> 8 9 /** 10 * 线程体数据结构 11 */ 12 typedef struct runner 13 { 14

关于Java中线程池的解读

之前的面试中多次被问到线程池的相关内容,所以在之后的时间内我仔细的学习了一下线程池的相关内容. 1.使用线程池的意义 复用:类似WEB服务器等系统,长期来看内部需要使用大量的线程处理请求,而单次请求响应时间通常比较短,此时Java基于操作系统的本地调用方式大量的创建和销毁线程本身会成为系统的一个性能瓶颈和资源浪费.若使用线程池技术可以实现工作线程的复用,即一个工作线程创建和销毁的生命周期期间内可以执行处理多个任务,从而总体上降低线程创建和销毁的频率和时间,提升了系统性能. 流控:服务器资源有限,

简易“线程池”在Python网络爬虫中的应用

一,我是如何使用Python抓取网页的 我知道Python有一个爬虫框架scrapy,但是目前还没有学习,并且也没有什么很棘手的的问题需要去使用一个爬虫框架,所以我就用Python自带的urllib,将目标网页爬下来,然后用正则过滤出自己需要的内容. 二,效率问题 上面的方法简单,真的是上手即用,但是问题是效率问题,如果一个网页一个网页的抓,显然带宽无法达到最高,浪费了大部分带宽,这时候大部分人都会想到,多线程啊! 对,但是我们大部分人又都会写出下面的代码 # 总任务数有500个 while i

python笔记——简易线程池multiprocessing.Pool

多线程模型设计是一个比较复杂的逻辑,但是python对于多线程的处理却有种种方便的类库,不需要过多的纠结线程间的操作细节.比如multiprocessing.Pool就是其中之一. 官方给的范例也很简单. from multiprocessing import Pool def f(x): return x*x if __name__ == '__main__': pool = Pool(processes=4) # start 4 worker processes result = pool.

使用 LinkedBlockingQueue 实现简易版线程池

前一阵子在做联系人的导入功能,使用POI组件解析Excel文件后获取到联系人列表,校验之后批量导入.单从技术层面来说,导入操作通常情况下是一个比较耗时的操作,而且如果联系人达到几万.几十万级别,必须拆分成为子任务来执行.综上,可以使用线程池来解决问题.技术选型上,没有采用已有的 ThreadPoolExecutor 框架,而使用了自制的简易版线程池.该简易版的线程池,其实也是一个简易版的[生产者-消费者]模型,任务的加入就像是生产的过程,任务的处理就像是消费的过程.我们在这里不去讨论方案的合理性

线程池实现

线程池实现 Table of Contents 1 基本设计思路 2 使用线程池的优势 3 TPTask 4 TPThread 5 ThreadPool 5.1 线程管理 5.2 并发任务管理 6 实现细节 6.1 线程回调函数 6.2 线程池管理 6.2.1 线程池初始化 6.2.2 并发任务添加 6.2.3 与主线程的交互 6.2.4 线程池销毁 7 总结 1 基本设计思路 我们首先设计TPThread类,用于管理单个线程的属性和方法:有了TPThread表示的线程之后,我们定义Thread

带线程池的socket客户端与服务端

前言 socket(套接字),Socket和ServerSocket位于java.net包中,之前虽然对socket有过一些了解,但一直都是云里雾里的,特意仔细的学习了一个socket,用socket模拟一个天气查询的功能,并且解决了几个使用socket过程中比较严重的问题. 最简单的客户端和服务端 服务端代码 1 package cn.hucc.socket.server; 2 3 import java.io.DataInputStream; 4 import java.io.DataOut

Java线程池实现原理与技术

本文将通过实现一个简易的线程池理解线程池的原理,以及介绍JDK中自带的线程池ThreadPoolExecutor和Executor框架. 1.无限制线程的缺陷 多线程的软件设计方法确实可以最大限度地发挥多核处理器的计算能力,提高生产系统的吞吐量和性能.但是,若不加控制和管理的随意使用线程,对系统的性能反而会产生不利的影响. 一种最为简单的线程创建和回收的方法类似如下: new Thread(new Runnable() { @Override public void run() { //do s

Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start(); 1 2 3 4 5 6 7 new Thread(new