精华内容
下载资源
问答
  • c++线程池设计与实现
    2013-11-24 20:26:57
    。。。
    更多相关内容
  • C++ 线程池设计

    2014-08-22 22:06:12
    线程池的任务就在于负责这些线程的创建,销毁和任务处理参数传递、唤醒和等待。1、创建若干线程,置入...5、如果创建失败或者线程池已满,根据设计策略选择返回错误或将任务置入处理队列,等待处理。6. 销毁线程池
  • C++线程池设计

    2019-02-22 17:06:32
    http://blog.csdn.net/ithzhang/article/details/9020283 代码https://github.com/ithzhang/ThreadpoolLib C++11 跨平台线程池https://www.cnblogs.com/linbc/p/5041648.html
    展开全文
  • 目录设计思路主线程运行逻辑task以及taskpool设计详细流程讲解完整代码打印结果往期回顾 设计思路 线程池实际上就是一组线程,当我们需要异步执行一些任务时,经常要通过OS频繁创建和销毁线程,不如直接创建一组在...

    设计思路

    线程池实际上就是一组线程,当我们需要异步执行一些任务时,经常要通过OS频繁创建和销毁线程,不如直接创建一组在程序生命周期内不会退出的线程。
    当有任务需要被执行时,线程可以自动地去拿任务并执行,在没有任务时,线程处于阻塞或者睡眠状态。
    我们选择队列存放任务,main函数中的thread作为任务的生产者,从队列尾部插入任务。线程池中的线程作为消费者,从队列头部获取任务。
    复杂考虑的话,当线程池的线程在处理任务的过程中也产生了关联任务,那么这个线程也是消费者。

    队列也可以设计得更加具有实用性,例如可以根据任务的优先级设计多个队列,然后线程根据优先级获取线程(也就是先查询高优先级的队列,为空再去查询低优先级的队列)。

    综上,我们的设计中会有多个线程访问任务队列,所以我们要解决线程池创建向队列投放任务从队列中获取任务的线程互斥性。
    同时线程池的清理退出线程池中的工作线程清理任务队列,也是需要考虑的。
    并且,为了能够详细获知多线程获取多任务的流程,我们需要对taskID和threadID进行输出打印,std::cout并不是线程安全的,所以我们也要实现互斥地cout。
    这里我们统一使用互斥量std::mutex+lock来实现互斥性

    主线程运行逻辑

    在这里插入图片描述

    task以及taskpool设计

    Task
    在这里插入图片描述
    TaskPool
    在这里插入图片描述
    内部变量
    在这里插入图片描述

    详细流程讲解

    1、创建线程池对象时,调用构造函数TaskPool(),并初始化布尔类型的标志m_bRunning为false,表示此时线程池对象中的线程不工作
    2、调用线程池对象的初始化函数init(),这里默认的线程数为5。

    • m_bRunning置为true,表示线程池对象中的线程应该开始运行了
    • 然后通过for循环,每次构造一个新的线程对象,并且绑定一个线程函数TaskPool::threadFunc,创建之后线程就开始工作了。然后打印出当前的线程id,注意此时需要上锁,保证cout输出正常。然后将线程对象送入m_threads数组
      3、接下来看看构造出来的每个线程在干啥:
    while(true)
    {
    	{
    		上锁,访问任务队列
    		// 注意由于队列本身是个多线程共享资源,所以对于队列取元素以及状态判断都是要先加锁再操作
    		队列为空则一直循环  // 为什么要用循环判断呢?
    		// 这是因为wait()从阻塞到返回,不一定就是由于notify_one()函数造成的,还有可能由于系统的不确定原因唤醒(可能和条件变量的实现机制有关),这个的时机和频率都是不确定的,被称作伪唤醒,如果在错误的时候被唤醒了,执行后面的语句就会错误,所以需要再次判断队列是否为空,如果还是为空,就继续wait()阻塞。
    		{
    			如果m_bRunning为false,说明此时应该中止线程操作,所以需要连着跳出两个循环,所以直接用goto label吧
    			否则就一直等待在这儿,wait()可以让线程陷入休眠状态,在消费者生产者模型中,如果生产者发现队列中没有东西,就可以让自己休眠.
    		}
    		此时 获取队头元素,并将队头元素出队
    	}
    	// 为了减少锁的粒度,接下来的操作不需要加锁了,因为已经拿到了队列中的元素
    	执行Task对象的doIt()方法,也就是打印任务id和线程id
    }
    label :
    打印当前线程id
    

    4、for循环,创建10个Task对象,然后调用addTask方法,将task送入线程池中的任务队列。显然push操作是互斥的,所以需要先上锁。然后打印任务id和线程id,最后通过条件变量的notify_one方法,通知一个挂起的线程去消费队列里面的任务。

    5、等待一段时间
    6、调用线程池对象的stop方法,先设置m_bRunning标志为false,然后通过条件变量的notify_all方法,通知挂起的或者正在运行的所有线程,结束线程函数运行。然后等待所有线程join之后,退出。
    7、跳出主线程,开始调用TaskPool对象的析构函数,也就是执行removeAllTasks方法,也就是将任务队列里面的存的task指针进行reset,也就是减引用计数,shared_ptr指针如果引用计数减为0,会自动调用析构函数。为了线程安全,我们同样需要对这块代码进行加锁。

    完整代码

    c++实现简单线程池代码

    打印结果

    Init a thread, id: 2
    Init a thread, id: 3
    Init a thread, id: 4
    Init a thread, id: 5
    Init a thread, id: 6
    add a Task, id: 0, thread id is: 1
    add a Task, id: 1, thread id is: 1
    add a Task, id: 2, thread id is: 1
    handle a task ,TaskID is: 1, thradID is:3
    a task destructed , TaskID is: 1, thradID is:3
    handle a task ,TaskID is: 2, thradID is:4
    a task destructed , TaskID is: 2, thradID is:4
    handle a task ,TaskID is: 0, thradID is:2
    a task destructed , TaskID is: 0, thradID is:2
    add a Task, id: 3, thread id is: 1
    handle a task ,TaskID is: 3, thradID is:3
    a task destructed , TaskID is: 3, thradID is:3
    handle a task ,TaskID is: 4, thradID is:5
    add a Task, id: 4, thread id is: 1
    a task destructed , TaskID is: 4, thradID is:1
    add a Task, id: 5, thread id is: 1
    handle a task ,TaskID is: 5, thradID is:4
    a task destructed , TaskID is: 5, thradID is:4
    add a Task, id: 6, thread id is: 1
    handle a task ,TaskID is: 6, thradID is:4
    a task destructed , TaskID is: 6, thradID is:4
    handle a task ,TaskID is: 7, thradID is:2
    add a Task, id: 7, thread id is: 1
    a task destructed , TaskID is: 7, thradID is:1
    add a Task, id: 8, thread id is: 1
    add a Task, id: 9, thread id is: 1
    handle a task ,TaskID is: 9, thradID is:6
    a task destructed , TaskID is: 9, thradID is:6
    handle a task ,TaskID is: 8, thradID is:5
    a task destructed , TaskID is: 8, thradID is:5
    exit thread , threadID:3
    exit thread , threadID:4
    exit thread , threadID:2
    exit thread , threadID:5
    exit thread , threadID:6
    
    Process finished with exit code 0
    
    

    往期回顾

    C++多线程快速入门(四)shared_mutex以及读写锁应用
    C++多线程快速入门(三):生产者消费者模型与条件变量使用
    C++多线程快速入门(二)共享数据同步以及数据竞争
    C++多线程快速入门(一):基本&常用操作

    展开全文
  • c++实现线程池

    千次阅读 2021-05-22 16:02:28
    一个简单的c++线程池实现如下所示: #include <iostream> #include <vector> #include <deque> #include <thread> #include <mutex> #include <condition_vari

    线程池技术是为了避免频繁的创建和销毁线程所带来的开销。
    线程池是一个典型的生产者-消费者模型,用户将要执行的任务添加到任务队列,并通知线程池,线程池则唤醒其中的一个线程来处理任务。一个简单的c++线程池实现如下所示:

    #include <iostream>
    #include <vector>
    #include <deque>
    #include <thread>
    #include <mutex>
    #include <condition_variable>
    #include <functional>
    #include <atomic>
    #include <unistd.h>
    
    using namespace std;
    
    class ThreadPool
    {
    public:
        using TaskEntry = function<void ()>;
    
        ThreadPool(int size)
        {
            running.store(false);
            stopflag.store(false);
            int enablecpunums = sysconf(_SC_NPROCESSORS_ONLN);
            threadpoolsize = (size > 0 && size < enablecpunums) ? size : enablecpunums;
        }
    
        ~ThreadPool()
        {
            if (running.load()) { stop(); }
        }
    
        void start()
        {
            running.store(true);
            threadbuckets.reserve(threadpoolsize);
            for (int i = 0; i < threadpoolsize; i++)
            {
                threadbuckets.emplace_back(new thread(bind(&ThreadPool::TaskInitEntry, this)));
            }
        }
    
        void stop()
        {
            stopflag.store(true);
            while (1)
            {
                threadpoolmutex.lock();
                int n = taskbuckets.size();
                threadpoolmutex.unlock();
                if (0 == n) break;
                usleep(500*1000);
            }
            running.store(false);
            threadpoolconvar.notify_all();
            for (int i = 0; i < threadpoolsize; i++)
            {
                threadbuckets[i]->join();
            }
        }
    
        void run(TaskEntry task)
        {
            if (stopflag.load() || !running.load() || !task) return;
            unique_lock<mutex> lock(threadpoolmutex);
            taskbuckets.push_back(task);
            threadpoolconvar.notify_one();
        }
    
    private:
        void TaskInitEntry()
        {
            while (running.load())
            {
                unique_lock<mutex> lock(threadpoolmutex);
                threadpoolconvar.wait(lock, [this]{ return !running.load() || !taskbuckets.empty(); });
                if (!running.load() && taskbuckets.empty()) return;
                TaskEntry task = taskbuckets.front();
                taskbuckets.pop_front();
                task();
            } 
        }
    
    private:
        atomic<bool> running;
        atomic<bool> stopflag;
        mutex threadpoolmutex;
        int threadpoolsize;
        condition_variable threadpoolconvar;
        vector<unique_ptr<thread>> threadbuckets;
        deque<TaskEntry> taskbuckets;
    };
    
    
    int main()
    {
        ThreadPool threadpool(8);
        threadpool.start();
        for (int i = 0; i < 100; i++)
        {
            threadpool.run([]{ cout << "abcdefg\n"; });
        }
        threadpool.stop();
        return 0;
    }
    
    

    参考资料:

    1. muduo ThreadPool源码
    2. https://github.com/progschj/ThreadPool/blob/master/ThreadPool.h
    展开全文
  • C/C++ 线程池类封装(核心线程与非核心线程-面向对象方法) 一. 所作优化 前面关于线程池的封装一帖,仅仅是将指定工作线程创建后就保持阻塞等待任务,相对来说比较简单。现在对线程池来进行一些优化: 设置核心...
  • C++简单线程池设计

    2013-03-13 23:17:24
    C++线程池的简单设计与实现,使用GCC编译,可自己改写为vs编译,使用pthread线程库和curl网络库。
  • 线程池类似于内存池,连接池等,在一开始创建好一定数量的线程,当有任务需要处理时,就将该任务丢进线程池的某个线程中处理,而不是每个任务都启动一个线程。使用线程池的好处在于,不需要频繁的创建线程,因为创建...
  • C++实现线程池

    2021-05-14 10:11:30
    今天呢,小懵白就给大家继续讲解C++如何实现封装线程池类。 第一步 首先,我们需要定义生产者、消费者的存储容器类型。在这里呢,消费者的容器是通过使用SLT中的vector容器来实现的:std::vectorstd::thread pool; ...
  • 手写C++线程池

    千次阅读 2020-07-21 10:27:33
    由于c++标准库没有提供线程池,但是很多时候,我们需要使用线程池来执行任务从而提高效率,这也避免了频繁的启动、终止线程所带来的损耗。 设计 由于C++在不同平台有不同的线程实现,因此,为了保证跨平台化与通用...
  • C++线程池的使用

    2019-01-13 23:57:14
    1.为了减少创建和销毁线程的次数,线程池设计的时候已经创建好了线程,直接使用即可. 2.实现多线程并发,提高管理效率,比如说有10个人去银行办业务,有3个窗口柜员,柜员就相当于3个线程,调用10个客户,每个...
  • 全网最牛的基于C++11新特性线程池设计与实现【linux服务器开发】 专注于服务器后台开发,包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程...
  • Tpool 是基于 POSIX pthread 的 C++ 线程池实现。 它的设计考虑到了简单性。 介绍 Tpool 非常易于使用。 假设你要编写一个web服务器,并在线程池中处理传入的请求,那么你可以编写如下代码来完成这个任务: # ...
  • C++线程池

    2021-03-17 15:31:47
    第六章 C++线程池 第七章 定时器 第八章 消息中心 第九章 网络访问器 第十章 HttpClient 第十一章 FTPClient 第十二章 Socket客户端 第十三章 Socket服务端 第十四章 WebSocket 大部分章节不会详细讲解,基本是以...
  • 1. 为什么要使用线程池 在实际使用中,线程是很占用系统资源的,如果对线程管理不善很容易导致系统问题。因此,在大多数并发框架中都会使用线程池来管理线程,使用线程池管理线程主要有如下好处: 降低资源消耗。...
  • 简介:线程池模式是指创建多个线程来执行多个任务,这些任务通常组织在一个队列中。正在执行的任务的结果也可能放在队列中,或者任务可能没有返回任何结果。通常,任务比线程多。一旦一个线程完成了它的任务,它就会...
  • 目录前言线程池组成线程池类的定义线程池类的实现完整代码 前言 在执行并行任务作业的场景时,需要使用到多个线程,如果每次使用到线程时再创建,不用就销毁,这样频繁的创建和销毁线程对于服务器是一个不小的开销。...
  • C++11线程池设计与实现 1.开发中用多线程还是多进程 2.如何使用C++11新特性实现线程池 3.如何实现多参数任务的支持 4.如何等待任务执行返回结果 5.C++20都出来了,别再说自己不懂C++11了 上课地址:...
  • C++ 线程池

    万次阅读 2019-08-05 14:04:02
    参考《深入学习C++11》 1概述 1.1设计目标 实现一个线程池,启动时开启n个线程。线程池中的线程从同步消息队列中取任务并执行 1.2线程池的好处 处理并发任务时,如果每来一个请求建立一个线程,大量的线程销毁...
  • linux下c++版本线程池的实现

    千次阅读 2022-04-01 11:27:28
    下面将直接上代码,同时这里需要主要的是使用的线程函数是linux自带的不是c++的自带线程函数,后续会使用c++提供一个线程池版本 目录 任务队列 头文件 源文件 线程池 线程池头文件 线程池源文件 测试代码 ...
  • 主要给大家介绍了关于C++实现线程池的简单方法,文中通过示例代码介绍的非常详细,对大家学习或者使用C++具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • 今天突然对前些日子一直很疑惑的c++线程池有了新的想法。其实所谓的线程池无非就是两个技术点,一个,多线程,指工作线程和主线程分离,或者说数据接收和处理分两个线程,一般就是讲需要运行的函数放到子线程执行,...
  • 并且创建线程池,将任务委派给线程池中的线程,以便使它们可以并发地执行。在高并发的情况下采用线程池,可以有效降低线程创建释放的时间花销及资源开销,如不使用线程池,有可能造成系统创建大量线程而导致消耗完...
  • #include <memory> #include <functional> #include <thread> #include <iostream> #include <vector> class Thread ... Thread(ThreadFunction func,int id):func_(func)
  • 包含两个队列,一个任务队列和一个线程队列。启动线程池前首先创建任务,将所有任务加入任务队列。 头文件thread_pool.h: #pragma once #include<condition_variable> #include<...dequ...
  •  使用多线程可以提高工作效率,这是毋容置疑的了,那怎么用多线程来设计程序呢?最简单、原始的方法就是,对于每一项工作,都创建一个线程去处理,直到这项工作结束,线程就结束,但这样做存在一个问题:如果每一项...
  • c++11线程池实现

    万次阅读 多人点赞 2015-07-22 00:01:39
    然而 c++ 对于多线程的支持还是比较低级,稍微高级一点的用法都需要自己去实现,譬如线程池、信号量等。线程池(thread pool)这个东西,在面试上多次被问到,一般的回答都是:“管理一个任务队列,一个线程队列,然后...
  • C++17 线程池

    2019-09-19 21:05:23
    线程池是一种池化资源技术,也是一种多线程模式。线程池通常序列化任务至队列,调度线程执行任务。 调度关键在于条件变量,当不满足执行条件时,运用阻塞和激活,及时让出处理器,在满足条件之前几乎不占用处理器,...
  • c++线程池

    2019-04-18 23:13:32
     深入解析C++编程中线程池的使用 转自: 深入解析C++编程中线程池的使用 为什么需要线程池 目前的大多数网络服务器,包括Web服务器、Email服务器以及数据库服务器等都具有一个共同点,就是单位时间内必须处理...
  • C++ 线程池设计问题

    2014-05-19 20:00:00
    1. 给用户添加任务的接口是 schedule(arg...问题:我写完thread_pool后才发现,用户不再知道如何去删除他创建的 Work了,因为线程池内保存着指向Work的指针,线程池是自动析构的,因此,这种设计方法不可行 b) 设计...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,780
精华内容 10,312
关键字:

c++线程池设计

c++ 订阅