【Windows】操作系统之线程池(第八篇)

目录

一、定义与概念

二、作用与优势

三、工作原理

四、关键参数

五、应用场景

六、C++中的线程池实现


线程池是一种多线程处理形式,它允许开发者在程序中创建和管理一组工作线程,这些线程可以共享资源,并按需执行任务。

一、定义与概念

线程池在处理过程中将任务添加到队列中,然后在创建线程后自动启动这些任务。这里的线程是指用于执行任务的线程,而任务则是指实现了Runnable或Callable接口的实例对象。线程池通过复用现有的线程来减少线程创建和销毁的开销,从而提高系统的运行效率。

二、作用与优势

  1. 限制线程数量:线程池可以根据系统的需求和硬件环境灵活控制线程的数量,避免创建过多的线程导致系统资源耗尽。
  2. 提高响应速度:当任务到达时,如果线程池中有空闲线程,则任务可以立即被执行,无需等待新线程的创建。
  3. 提高线程的可管理性:线程池可以对所有线程进行统一的管理和控制,便于监控和调优。
  4. 减少系统开销:通过复用线程,线程池减少了线程创建和销毁的次数,降低了系统资源的消耗。

三、工作原理

线程池的工作流程大致如下:

  1. 当有新任务提交时,线程池会首先检查核心线程数(corePoolSize)是否已满。如果未满,则创建新线程执行任务;如果已满,则检查任务队列(workQueue)是否已满。
  2. 如果任务队列未满,则将任务添加到任务队列中等待执行;如果任务队列已满,则检查线程池中的线程数是否达到了最大线程数(maximumPoolSize)。
  3. 如果线程数未达到最大线程数,则创建新线程执行任务;如果线程数已达到最大线程数,则根据配置的拒绝策略(RejectedExecutionHandler)处理无法执行的任务。

四、关键参数

线程池的关键参数包括:

  • 核心线程数(corePoolSize):线程池中的核心线程数,即使这些线程空闲,线程池也不会销毁它们。
  • 最大线程数(maximumPoolSize):线程池中允许的最大线程数。
  • 最大空闲时间(keepAliveTime):当线程数大于核心线程数时,这是多余空闲线程在终止前等待新任务的最长时间。
  • 任务队列(workQueue):用于存放等待执行的任务的阻塞队列。
  • 线程工厂(ThreadFactory):用于创建新线程的工厂。
  • 拒绝策略(RejectedExecutionHandler):当任务无法被线程池执行时(即线程池已满且任务队列也满),所采取的拒绝策略。

五、应用场景

线程池适用于多种并发场景,如:

  • 网购商品秒杀:在秒杀活动中,由于用户请求量巨大,使用线程池可以有效地管理并发请求,提高系统响应速度。
  • 云盘文件上传和下载:在处理大量文件上传和下载任务时,线程池可以复用线程资源,提高处理效率。
  • 网上购票系统:在高峰期,网上购票系统需要处理大量的购票请求,使用线程池可以有效地管理这些请求,避免系统崩溃。

六、C++中的线程池实现

#include <iostream>  
#include <vector>  
#include <queue>  
#include <thread>  
#include <mutex>  
#include <condition_variable>  
#include <future>  
  
class ThreadPool {  
public:  
    ThreadPool(size_t threads) : stop(false) {  
        for(size_t i = 0; i<threads; ++i)  
            workers.emplace_back(  
                [this]  
                {  
                    while(true) {  
                        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 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);  
  
            // don't allow enqueueing after stopping the pool  
            if(stop)  
                throw std::runtime_error("enqueue on stopped ThreadPool");  
  
            tasks.emplace([task](){ (*task)(); });  
        }  
        condition.notify_one();  
        return res;  
    }  
  
    ~ThreadPool() {  
        {  
            std::unique_lock<std::mutex> lock(queue_mutex);  
            stop = true;  
        }  
        condition.notify_all();  
        for(std::thread &worker: workers)  
            worker.join();  
    }  
private:  
    std::vector<std::thread> workers;  
    std::queue<std::function<void()>> tasks;  
  
    std::mutex queue_mutex;  
    std::condition_variable condition;  
    bool stop;  
};  
  
// 使用线程池  
int main() {  
    ThreadPool pool(4);  
  
    auto result1 = pool.enqueue([](int answer) { return answer; }, 42);  
    auto result2 = pool.enqueue([](std::string msg) { return msg; }, "hello");  
  
    std::cout << "result1: " << result1.get() << std::endl;  
    std::cout << "result2: " << result2.get() << std::endl;  
  
    return 0;  
}

这段代码实现了一个基本的线程池,其中包含了以下部分:

  • 一个ThreadPool类,它接受线程数量作为构造函数的参数。
  • 使用std::vector<std::thread>来存储工作线程。
  • 使用std::queue<std::function<void()>>来管理任务队列。
  • 使用std::mutexstd::condition_variable来同步线程。
  • enqueue方法允许向线程池添加任务,并返回一个std::future对象,以便稍后获取任务的结果。
  • 析构函数确保所有任务都已完成,并且所有工作线程都已正确终止。

综上所述,线程池是一种高效的并发处理机制,通过复用线程资源、限制线程数量等方式提高了系统的运行效率和稳定性。在Java等编程语言中,线程池的实现提供了丰富的功能和灵活的配置选项,使得开发者能够根据实际场景选择最合适的线程池策略。

  • 27
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱编程的小猴

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

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

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

打赏作者

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

抵扣说明:

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

余额充值