如何利用线程池调用其他函数
时间: 2023-06-29 14:17:47 浏览: 132
如何使用线程池
4星 · 用户满意度95%
要利用线程池调用其他函数,需要将需要执行的函数封装成一个任务(Task),并将任务提交给线程池。下面是一个简单的例子:
```c++
#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
class ThreadPool {
public:
using Task = std::function<void()>;
explicit ThreadPool(std::size_t numThreads) {
start(numThreads);
}
~ThreadPool() {
stop();
}
template<class T>
auto enqueue(T task) -> std::future<decltype(task())> {
auto wrapper = std::make_shared<std::packaged_task<decltype(task()) ()>>(std::move(task));
{
std::unique_lock<std::mutex> lock{mEventMutex};
mTasks.emplace([=] {
(*wrapper)();
});
}
mEventVar.notify_one();
return wrapper->get_future();
}
private:
std::vector<std::thread> mThreads;
std::condition_variable mEventVar;
std::mutex mEventMutex;
bool mStopping = false;
std::queue<Task> mTasks;
void start(std::size_t numThreads) {
for (auto i = 0u; i < numThreads; ++i) {
mThreads.emplace_back([=] {
while (true) {
Task task;
{
std::unique_lock<std::mutex> lock{mEventMutex};
mEventVar.wait(lock, [=] { return mStopping || !mTasks.empty(); });
if (mStopping && mTasks.empty())
break;
task = std::move(mTasks.front());
mTasks.pop();
}
task();
}
});
}
}
void stop() noexcept {
{
std::unique_lock<std::mutex> lock{mEventMutex};
mStopping = true;
}
mEventVar.notify_all();
for (auto &thread : mThreads)
thread.join();
}
};
void foo(int num) {
std::cout << "Thread " << std::this_thread::get_id() << " executing foo(" << num << ")" << std::endl;
}
int main() {
ThreadPool pool{4};
for (int i = 0; i < 8; ++i) {
pool.enqueue([=] {
foo(i);
});
}
return 0;
}
```
在这个例子中,我们定义了一个线程池 `ThreadPool`,它接受一个 `numThreads` 参数,表示线程池中工作的线程数。线程池中的每个线程都会不断地从任务队列中取出任务,并执行任务。
我们还定义了一个 `Task` 类型,它是一个函数对象类型,可以封装任何可调用对象。
在 `ThreadPool` 中,我们定义了一个 `enqueue` 函数模板,它接受一个可调用对象 `task`,将其封装成一个 `Task` 对象,并将其提交给任务队列。该函数返回一个 `std::future` 对象,用于获取任务的返回值。
在 `main` 函数中,我们创建了一个线程池,并提交了 8 个任务到线程池中。每个任务都是一个 lambda 函数,用于调用函数 `foo`,并传递一个整数参数。函数 `foo` 将在线程池中的一个线程中执行,并打印输出。
需要注意的是,由于线程池中的线程是异步执行的,因此 `foo` 函数的输出顺序可能会与任务提交的顺序不同。
阅读全文