C++线程池实现

一、线程池简介

一个线程池是由若干在等待任务的线程组成的线程池,当请求到来时,将任务分配给其中一个空闲线程执行;当任务执行完毕后,线程并没有结束,而是继续等待下一个任务。在服务器程序中,很多请求都是短时间的,大部分处理时间却是在等待数据的IO操作上,因此线程池可以极大地提高服务器的并发能力和响应速度。

二、C++线程池实现原理

1. 首先,我们需要引入常见的C++并发库,如<mutex><thread>等。

    #include <mutex>
    #include <thread>

2. 声明一个线程池类ThreadPool。

    class ThreadPool {
    public:
        //声明构造函数、析构函数、添加任务函数等
    private:
        //声明任务队列、线程池等变量
    };

3. 在构造函数中,初始化线程池和任务队列。

    ThreadPool::ThreadPool(int size) {
        for (int i = 0; i < size; i++) {
            //创建线程,将线程函数设置为work函数
            //存储线程到线程池中
            //设置线程为detachable,即自动释放
        }
    }

4. 添加任务函数需要将任务加入任务队列,唤醒等待线程,通知有新的任务需要执行。

    template <class F, class... Args>
    auto ThreadPool::enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
        //获取任务返回值类型
        using return_type = typename std::result_of<F(Args...)>::type;
        //将任务和返回值类型build成packaged_task
        auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
        //使用future获取异步返回值
        std::future<return_type> res = task->get_future();
        {
            //加锁保证对任务队列的操作是原子的
            std::unique_lock<std::mutex> lock(queue_mutex);
            //将任务加入队列
            tasks.emplace([task]() { (*task)(); });
        }
        //唤醒等待线程,通知有新的任务需要执行
        condition.notify_one();
        return res;
    }

三、C++线程池实现代码示例

下面是ThreadPool类的完整代码示例:

#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>

class ThreadPool {
public:
    //构造函数,初始化线程池和任务队列
    ThreadPool(int size) {
        for (int i = 0; i < size; i++) {
            threads.emplace_back(std::thread(&ThreadPool::work, this));
            threads.back().detach();
        }
    }

    //析构函数,回收线程池
    ~ThreadPool() {}

    //添加任务函数,将任务加入任务队列,唤醒等待线程,通知有新的任务需要执行
    template <class F, class... Args>
    auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
        //获取任务返回值类型
        using return_type = typename std::result_of<F(Args...)>::type;
        //将任务和返回值类型build成packaged_task
        auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
        //使用future获取异步返回值
        std::future<return_type> res = task->get_future();
        {
            //加锁保证对任务队列的操作是原子的
            std::unique_lock<std::mutex> lock(queue_mutex);
            //将任务加入队列
            tasks.emplace([task]() { (*task)(); });
        }
        //唤醒等待线程,通知有新的任务需要执行
        condition.notify_one();
        return res;
    }

private:
    //执行任务函数
    void work() {
        while (true) {
            std::function<void()> task;
            {
                //加锁保证对任务队列的操作是原子的
                std::unique_lock<std::mutex> lock(queue_mutex);
                //等待任务队列非空
                condition.wait(lock, [this]() { return !tasks.empty(); });
                //取出队列中的一个任务
                task = std::move(tasks.front());
                tasks.pop();
            }
            //执行任务
            task();
        }
    }

private:
    //线程池
    std::vector<std::thread> threads;
    //任务队列
    std::queue<std::function<void()>> tasks;
    //队列锁
    std::mutex queue_mutex;
    //任务队列非空条件变量
    std::condition_variable condition;
}

四、线程池实现应用场景

线程池适用于很多需要处理大量短时间任务的场景,比如网络服务器、图像处理、视频处理等。一些大型框架,如Web服务器或消息总线系统,会使用线程池来处理并发请求,这样可以大大提高响应速度和扩展能力。

五、总结

通过C++线程池实现,我们可以实现多线程任务的快速处理,提高系统的并发处理能力和响应速度,并且保证线程的可控性、执行流程的正确性和程序的高效性。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/198642.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-04 10:27
下一篇 2024-12-04 10:27

相关推荐

  • Python线程等待指南

    本文将从多个方面详细讲解Python线程等待的相关知识。 一、等待线程结束 在多线程编程中,经常需要等待线程执行完毕再进行下一步操作。可以使用join()方法实现等待线程执行完毕再…

    编程 2025-04-29
  • Python两个线程交替打印1到100

    这篇文章的主题是关于Python多线程的应用。我们将会通过实际的代码,学习如何使用Python两个线程交替打印1到100。 一、创建线程 在Python中,我们可以使用Thread…

    编程 2025-04-28
  • ROS线程发布消息异常解决方法

    针对ROS线程发布消息异常问题,我们可以从以下几个方面进行分析和解决。 一、检查ROS代码是否正确 首先,我们需要检查ROS代码是否正确。可能会出现的问题包括: 是否正确初始化RO…

    编程 2025-04-28
  • Python线程池并发爬虫

    Python线程池并发爬虫是实现多线程爬取数据的常用技术之一,可以在一定程度上提高爬取效率和数据处理能力。本文将从多个方面对Python线程池并发爬虫做详细的阐述,包括线程池的实现…

    编程 2025-04-27
  • 线程池中的一个线程异常了会被怎么处理

    本文将从以下几个方面对线程池中的一个线程异常了会被怎么处理进行详细阐述:异常的类型、如何捕获异常、异常的处理方式。 一、异常的类型 在线程池中,可以出现多种类型的异常,例如线程执行…

    编程 2025-04-27
  • 线程池的七个参数

    在多线程编程中,线程池是一种非常重要的编程模型,可以解决线程创建销毁的开销问题,提高程序的效率。在使用线程池时,需要对其七个参数进行配置,以达到最佳性能。下面将从多个方面详细阐述线…

    编程 2025-04-25
  • Java DelayQueue:实现延迟任务的线程安全队列

    一、DelayQueue的概述 Java的DelayQueue 是一个阻塞队列队列,主要用来实现对延迟任务的调度,也就是在指定的时间之后才能够取出任务来执行。该队列中保存的元素都必…

    编程 2025-04-23
  • 浏览器线程——从多个方面深入探讨

    一、浏览器线程的概念 浏览器线程是指浏览器中用于处理不同任务的线程。默认情况下,每个标签页都会有一个独立的进程,每个进程再包含多个线程,这些线程通过协同工作来完成浏览器的各项任务。…

    编程 2025-04-23
  • JMeter线程组详解

    一、线程组简介 JMeter作为一个负载测试工具,线程组是JMeter中非常重要的一个概念,它被用来模拟请求的发送。 简单来说,JMeter通过线程组来同时模拟多个用户对被测试的W…

    编程 2025-04-23
  • Java线程安全的集合

    Java的集合框架是广泛使用的标准库之一,它被设计为高效、灵活和安全。在多线程环境中,线程安全的集合至关重要,因为多个线程同时对同一个集合进行读写操作可能会导致数据的不一致和线程安…

    编程 2025-04-22

发表回复

登录后才能评论