C++编程: 线程池封装、任务异步执行以及任务延迟执行

0. 概述

本文将介绍如何使用C++11的标准库进行异步执行函数的封装,涵盖以下几个方面:

  • 异步执行阻塞或CPU密集型任务
  • 延迟执行函数的实现
  • 使用线程池进行任务管理和调度
  • 提供立即异步执行函数 really_async 和延迟执行函数 delay_call

1. 线程池的封装

1.1 线程池类设计

#include <vector>
#include <queue>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <stdexcept>
#include <future>

class ThreadPool {
public:
    explicit ThreadPool(size_t threads);
    template<class F, class... Args>
    auto enqueue(F&& f, Args&&... args) 
        -> std::future<typename std::result_of<F(Args...)>::type>;
    ~ThreadPool();

private:
    std::vector<std::thread> workers;
    std::queue<std::function<void()>> tasks;
    
    std::mutex queue_mutex;
    std::condition_variable condition;
    bool stop;
};

ThreadPool::ThreadPool(size_t threads) : stop(false) {
    for (size_t i = 0; i < threads; ++i) {
        workers.emplace_back([this] {
            for (;;) {
                std::function<void()> task;
                {
                    std::unique_lock<std::mutex> lock(this->queue_mutex);
                    this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); });
                    if (this->stop && this->tasks.empty())
                        return;
                    task = std::move(this->tasks.front());
                    this->tasks.pop();
                }
                task();
            }
        });
    }
}

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;

    auto task = std::make_shared<std::packaged_task<return_type()>>(
        std::bind(std::forward<F>(f), std::forward<Args>(args)...)
    );

    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        if (stop)
            throw std::runtime_error("enqueue on stopped ThreadPool");

        tasks.emplace([task] { (*task)(); });
    }
    condition.notify_one();
    return res;
}

ThreadPool::~ThreadPool() {
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        stop = true;
    }
    condition.notify_all();
    for (std::thread &worker : workers)
        worker.join();
}

class ThreadPoolSingleton {
public:
    static ThreadPoolSingleton& instance() {
        static ThreadPoolSingleton instance;
        return instance;
    }

    ThreadPool& pool() { return _pool; }

private:
    ThreadPoolSingleton() : _pool(10) {}
    ~ThreadPoolSingleton() = default;
    ThreadPool _pool;
};
#endif

1.2 流程图

启动线程池
创建多个线程
等待任务
分配任务
执行任务
任务完成
线程池销毁

2. 异步执行函数

#include <functional>
#include <thread>
#include <future>

template <typename Callable, typename... Args>
void really_async(Callable&& f, Args&&... args) {
    auto task = std::make_shared<std::packaged_task<void()>>(
        std::bind(std::forward<Callable>(f), std::forward<Args>(args)...)
    );

#ifdef NOT_USE_THREAD_POOL
    std::thread([task]() { (*task)(); }).detach();
#else
    auto& pool = ThreadPoolSingleton::instance().pool();
    pool.enqueue([task]() { (*task)(); });
#endif
}

2.1流程图

调用really_async
创建任务
是否使用线程池
将任务加入线程池
启动新线程执行任务
任务执行
任务完成

3. 延迟异步执行函数

#include <functional>
#include <thread>
#include <chrono>

template <class Callable, class... Args>
void delay_call(int after, bool async, Callable&& f, Args&&... args) {
    auto task = std::make_shared<std::packaged_task<void()>>(
        std::bind(std::forward<Callable>(f), std::forward<Args>(args)...)
    );

    if (async) {
#ifdef NOT_USE_THREAD_POOL
        std::thread([after, task]() {
            std::this_thread::sleep_for(std::chrono::milliseconds(after));
            (*task)();
        }).detach();
#else
        auto& pool = ThreadPoolSingleton::instance().pool();
        pool.enqueue([after, task]() {
            std::this_thread::sleep_for(std::chrono::milliseconds(after));
            (*task)();
        });
#endif
    } else {
        std::this_thread::sleep_for(std::chrono::milliseconds(after));
        (*task)();
    }
}

3.1 流程图

调用delay_call
创建任务
是否异步执行
是否使用线程池
将任务加入线程池
启动新线程执行任务
延迟执行任务
延迟执行任务
任务完成

4. 完整代码 call_async.hpp

#pragma once

#include <functional>
#include <chrono>
#include <future>
#include <thread>

// #define NOT_USE_THREAD_POOL
#ifndef NOT_USE_THREAD_POOL
#include "thread_pool.hpp"
#endif

template <typename Callable, typename... Args>
void really_async(Callable&& f, Args&&... args) {
    auto task = std::make_shared<std::packaged_task<void()>>(
        std::bind(std::forward<Callable>(f), std::forward<Args>(args)...)
    );

#ifdef NOT_USE_THREAD_POOL
    std::thread([task]() { (*task)(); }).detach();
#else
    auto& pool = ThreadPoolSingleton::instance().pool();
    pool.enqueue([task]() { (*task)(); });
#endif
}

template <class Callable, class... Args>
void delay_call(int after, bool async, Callable&& f, Args&&... args) {
    auto task = std::make_shared<std::packaged_task<void()>>(
        std::bind(std::forward<Callable>(f), std::forward<Args>(args)...)
    );

    if (async) {
#ifdef NOT_USE_THREAD_POOL
        std::thread([after, task]() {
            std::this_thread::sleep_for(std::chrono::milliseconds(after));
            (*task)();
        }).detach();
#else
        auto& pool = ThreadPoolSingleton::instance().pool();
        pool.enqueue([after, task]() {
            std::this_thread::sleep_for(std::chrono::milliseconds(after));
            (*task)();
        });
#endif
    } else {
        std::this_thread::sleep_for(std::chrono::milliseconds(after));
        (*task)();
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘色的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值