JJJ69 2024-04-24 11:36 采纳率: 92.4%
浏览 76
已结题

C++中的线程池与异步编程?

C++中的线程池与异步编程:

介绍C++中实现线程池的常见方法,如使用std::thread和std::queue构建简易线程池,或者使用第三方库(如boost::asio、cpp-taskflow等)。探讨如何利用线程池进行异步任务调度和并发编程。
  • 写回答

7条回答 默认 最新

  • 生瓜蛋子 2024-04-24 12:26
    关注

    在C++中,线程池(Thread Pool)和异步编程是两种用于并发执行任务以提高程序性能的技术。线程池是一种实现多线程编程的高效方式,它预先创建一组工作线程,将待处理的任务放入队列中,由线程池中的空闲线程依次取出并执行。异步编程则是通过非阻塞操作和回调机制,使得程序在等待某个任务完成时不会阻塞主线程,而是继续执行其他任务,待原任务完成后通过回调通知程序。两者在实际应用中常常结合使用,以充分利用多核处理器的优势,提高程序的响应速度和吞吐量。

    线程池

    线程池的主要优点包括:

    1. 资源复用:避免频繁创建和销毁线程带来的开销,线程池中的线程可以被反复使用,提高了系统的整体性能。

    2. 任务调度:线程池可以根据当前系统负载动态调整工作线程的数量,合理分配资源,避免过度竞争。

    3. 易于管理:线程池对线程进行集中管理,简化了线程同步和互斥问题,降低了编程难度。

    在C++中,可以使用标准库提供的std::threadstd::queue等组件自定义线程池,也可以使用第三方库如boost::asioIntel TBBfolly::ThreadPoolExecutor等提供的现成线程池实现。

    以下是一个简单的线程池实现示例:

    #include <iostream>
    #include <queue>
    #include <thread>
    #include <mutex>
    #include <condition_variable>
    
    class ThreadPool {
    public:
        ThreadPool(size_t num_threads) {
            for (size_t i = 0; i < num_threads; ++i) {
                workers_.emplace_back([this]() {
                    while (true) {
                        std::function<void()> task;
                        {
                            std::unique_lock<std::mutex> lock(mutex_);
                            condition_.wait(lock, [this]{ return stop_ || !tasks_.empty(); });
                            if (stop_ && tasks_.empty())
                                return;
                            task = std::move(tasks_.front());
                            tasks_.pop();
                        }
                        task();
                    }
                });
            }
        }
    
        ~ThreadPool() {
            {
                std::unique_lock<std::mutex> lock(mutex_);
                stop_ = true;
            }
            condition_.notify_all();
            for (std::thread &worker : workers_) {
                worker.join();
            }
        }
    
        template <typename F>
        void enqueue(F &&f) {
            if (stop_)
                throw std::runtime_error("enqueue on stopped ThreadPool");
    
            {
                std::lock_guard<std::mutex> lock(mutex_);
                tasks_.emplace(std::forward<F>(f));
            }
            condition_.notify_one();
        }
    
    private:
        std::vector<std::thread> workers_;
        std::queue<std::function<void()>> tasks_;
        std::mutex mutex_;
        std::condition_variable condition_;
        bool stop_ = false;
    };
    
    int main() {
        ThreadPool pool(4);
    
        for (int i = 0; i < 10; ++i) {
            int task_id = i;
            pool.enqueue([task_id]() {
                std::cout << "Task " << task_id << " is running on thread " << std::this_thread::get_id() << std::endl;
            });
        }
    
        return 0;
    }
    

    异步编程

    异步编程的核心思想是让程序在发起一个耗时操作(如I/O操作、网络请求、计算密集型任务等)时不等待其完成,而是立即返回并继续执行其他任务。当耗时操作完成后,通过回调函数、事件、future/promise等机制通知程序处理结果。

    C++11及以后的标准库提供了std::asyncstd::futurestd::promise等工具支持异步编程。例如,使用std::asyncstd::future实现异步计算:

    #include <future>
    #include <iostream>
    
    double compute_expensive_value(int n) {
        // Simulate a long-running computation
        std::this_thread::sleep_for(std::chrono::seconds(1));
        return static_cast<double>(n) * n;
    }
    
    int main() {
        // Launch an asynchronous task
        std::future<double> result_future = std::async(std::launch::async, compute_expensive_value, 10);
    
        std::cout << "Doing other work while the expensive value is being computed..." << std::endl;
    
        // Retrieve the result when ready
        double result = result_future.get();
        std::cout << "Computed value: " << result << std::endl;
    
        return 0;
    }
    

    结合使用

    线程池和异步编程可以很好地结合起来,线程池负责管理和调度线程资源,异步编程负责描述任务间的依赖关系和回调逻辑。例如,在线程池中执行异步任务:

    #include <future>
    #include <thread>
    #include <vector>
    #include <iostream>
    
    void do_work(int id, std::promise<void>&& complete_promise) {
        std::cout << "Worker " << id << " started\n";
        std::this_thread::sleep_for(std::chrono::seconds(1));  // Simulate some work
        std::cout << "Worker " << id << " finished\n";
        complete_promise.set_value();  // Notify completion
    }
    
    int main() {
        std::vector<std::future<void>> futures;
        std::vector<std::promise<void>> promises(4);  // Create promises for each task
    
        ThreadPool pool(4);  // Assuming you have a ThreadPool implementation
    
        for (int i = 0; i < 4; ++i) {
            futures.push_back(pool.enqueue([&promises, i]() {
                do_work(i, std::move(promises[i]));  // Pass the promise to the worker
            }));
        }
    
        // Wait for all tasks to complete
        for (auto& future : futures) {
            future.get();
        }
    
        std::cout << "All tasks completed\n";
    
        return 0;
    }
    

    通过这种方式,程序可以高效地并发执行多个异步任务,同时利用线程池进行资源管理和调度,提高了程序的整体性能和响应能力。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(6条)

报告相同问题?

问题事件

  • 系统已结题 5月2日
  • 已采纳回答 4月24日
  • 创建了问题 4月24日

悬赏问题

  • ¥15 关于#单片机#的问题:以ATMEGA128或相近型号单片机为控制器设计直流电机调速的闭环控制系统(相关搜索:设计报告|软件设计|流程图)
  • ¥15 打开软件提示错误:failed to get wglChoosePixelFormatARB
  • ¥15 (标签-python|关键词-char)
  • ¥15 python+selenium,在新增时弹出了一个输入框
  • ¥15 苹果验机结果的api接口哪里有??单次调用1毛钱及以下。
  • ¥20 学生成绩管理系统设计
  • ¥15 来一个cc穿盾脚本开发者
  • ¥15 CST2023安装报错
  • ¥15 使用diffusionbert生成文字 结果是PAD和UNK怎么办
  • ¥15 有人懂怎么做大模型的客服系统吗?卡住了卡住了