在现代软件开发中,多线程编程是提高程序性能的重要手段。C++11标准引入了对多线程的原生支持,使得在C++中实现多线程变得相对简单。本文将介绍如何在C++11中实现一个线程池,以及如何使用线程池来提交异步和同步任务。
线程池是一种线程使用模式,它维护多个线程,并将任务分配给这些线程执行。线程池的主要优点是可以减少线程创建和销毁的开销,提高资源利用率,并且可以控制同时运行的线程数量,避免过多的线程竞争导致的性能问题。
在C++11中,可以使用std::thread
来创建线程,使用std::function
来存储任务,使用std::mutex
和std::condition_variable
来实现线程同步。
异步任务是指提交给线程池后,立即返回,不等待任务完成的任务。在实现时,只需要将任务添加到任务队列中,并通知线程池有新任务即可。
void WorkerThread::doAsync(const std::function& t) {
std::lock_guard lock(mutex);
tasks.push_back(t);
itemInQueue.notify_one();
}
同步任务是指提交给线程池后,需要等待任务完成的任务。在实现时,需要在任务完成后通知提交任务的线程。
void WorkerThread::doSync(const std::function& t) {
std::condition_variable event;
bool finished = false;
std::unique_lock lock(mutex);
auto lambda = [this, &t, &finished, &event]() {
t();
std::lock_guard lock(mutex);
finished = true;
event.notify_one();
};
tasks.push_back(lambda);
itemInQueue.notify_one();
while(!finished) event.wait(lock);
}
线程池需要在程序开始时启动,在程序结束时停止。可以通过一个循环来不断从任务队列中取出任务并执行,直到线程池停止。
void WorkerThread::startThread() {
std::unique_lock lock(mutex);
do {
while(isRunning && tasks.empty()) itemInQueue.wait(lock);
while(!tasks.empty()) {
auto size = tasks.size();
printf("Number of pending task are %d\n", size);
const std::function t = tasks.front();
tasks.pop_front();
lock.unlock();
t();
lock.lock();
}
itemInQueue.notify_all();
} while(isRunning);
itemInQueue.notify_all();
}
#include
#include
#include
#include "workerthread.h"
int main() {
std::cout << "Hi, Welcome to demo of worker thread" << std::endl;
{
// Create two worker threads
WorkerThread thread1;
WorkerThread thread2;
// Example of a synchronous task
thread1.doSync([]() {
std::cout << "First - blocking call" << std::endl;
});
for(int i = 1; i < 100; i++) {
auto& t = i % 2 == 0 ? thread1 : thread2;
if(i == 10) {
// Another synchronous task in between
thread1.doSync([]() {
std::cout << "Second - blocking call" << std::endl;
});
}
// Multiple asynchronous tasks queued
t.doAsync([i]() {
std::this_thread::sleep_for(std::chrono::duration(200));
std::cout << (i % 2 == 0 ? "thread1-" : "thread2-") << "iteration number: " << i << std::endl;
});
}
thread1.doSync([]() {
std::cout << "Last - blocking call" << std::endl;
});
}
// Added extra scope to demo destruction of worker thread
std::cout << "This must be last line\n";
}