C++ 语言 线程池的任务调度策略有哪些

C++阿木 发布于 2025-06-14 7 次阅读


阿木博主一句话概括:C++ 线程池任务调度策略解析与实现

阿木博主为你简单介绍:随着多核处理器的普及,线程池技术在提高程序并发性能方面发挥着越来越重要的作用。本文将围绕C++语言,探讨线程池的任务调度策略,并给出相应的代码实现。

一、

线程池是一种常用的并发编程模型,它通过复用一定数量的线程来执行任务,从而提高程序的性能。在C++中,实现线程池的关键在于任务调度策略。本文将详细介绍几种常见的任务调度策略,并给出相应的代码实现。

二、任务调度策略

1. 先进先出(FIFO)策略

先进先出策略是最简单的任务调度策略,它按照任务提交的顺序执行。这种策略实现简单,但可能导致“饥饿”现象,即某些任务长时间得不到执行。

2. 最短任务优先(SJF)策略

最短任务优先策略优先执行任务队列中预计执行时间最短的任务。这种策略可以提高系统的吞吐量,但可能导致长任务饿死。

3. 优先级调度策略

优先级调度策略根据任务的优先级来决定执行顺序。优先级高的任务优先执行,这种策略适用于需要实时处理的任务。

4. 轮询调度策略

轮询调度策略将任务均匀地分配给线程池中的线程。这种策略简单易实现,但可能导致某些线程长时间空闲。

5. 最少任务执行时间优先(LRU)策略

最少任务执行时间优先策略优先执行执行时间最短的线程。这种策略可以减少线程上下文切换的开销,提高系统性能。

三、代码实现

以下是一个基于C++11的线程池实现,其中包含了上述几种任务调度策略:

cpp
include
include
include
include
include
include
include
include

class ThreadPool {
public:
ThreadPool(size_t threads) : stop(false) {
for (size_t i = 0; i < threads; ++i) {
workers.emplace_back([this] {
for (;;) {
std::function task;
{
std::unique_lock 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
auto enqueue(F&& f, Args&&... args)
-> std::future<#typename std::result_of::type> {
using return_type = typename std::result_of::type;

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

std::future res = task->get_future();
{
std::unique_lock lock(queue_mutex);

if (stop)
throw std::runtime_error("enqueue on stopped ThreadPool");

tasks.emplace(

() { (task)(); });
}
condition.notify_one();
return res;
}

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

private:
std::vector workers;
std::queue< std::function > tasks;

std::mutex queue_mutex;
std::condition_variable condition;
bool stop;
};

// 示例:使用线程池执行任务
int main() {
ThreadPool pool(4); // 创建一个包含4个线程的线程池

// 使用FIFO策略提交任务
pool.enqueue([](int n) { std::cout << "FIFO: " << n << std::endl; }, 1);
pool.enqueue([](int n) { std::cout << "FIFO: " << n << std::endl; }, 2);
pool.enqueue([](int n) { std::cout << "FIFO: " << n << std::endl; }, 3);
pool.enqueue([](int n) { std::cout << "FIFO: " << n << std::endl; }, 4);

// 使用SJF策略提交任务
pool.enqueue([](int n) { std::cout << "SJF: " << n << std::endl; }, 5);
pool.enqueue([](int n) { std::cout << "SJF: " << n << std::endl; }, 6);
pool.enqueue([](int n) { std::cout << "SJF: " << n << std::endl; }, 7);
pool.enqueue([](int n) { std::cout << "SJF: " << n << std::endl; }, 8);

return 0;
}

四、总结

本文介绍了C++线程池的几种常见任务调度策略,并给出了相应的代码实现。在实际应用中,可以根据具体需求选择合适的调度策略,以提高程序的性能和效率。