@@ -113,7 +113,6 @@ int main() {
113
113
114
114
> [运行](https://godbolt.org/z/h5G5hTT4a)测试。
115
115
116
-
117
116
- 创建线程池时,指定线程数量,线程池会创建对应数量的线程。
118
117
119
118
- 使用 `boost::asio::post` 提交任务,任务会被添加到任务队列中。
@@ -168,6 +167,73 @@ boost::asio::post(pool, task); // 将任务加入线程池
168
167
pool.join(); // 等待任务完成 (或者析构自动调用)
169
168
```
170
169
170
+ ### `QThreadPool`
171
+
172
+ [`QThreadPool`](https://doc.qt.io/qt-6/qthreadpool.html) 是 Qt 提供的线程池实现,它是用来管理自家的 `QThreads` 的集合。
173
+
174
+ ```cpp
175
+ #include <QCoreApplication>
176
+ #include <QThreadPool>
177
+ #include <QRunnable>
178
+ #include <QDebug>
179
+
180
+ struct MyTask : public QRunnable{
181
+ void run() override {
182
+ qDebug() << "🐢🐢🐢🐢🐢";
183
+ }
184
+ };
185
+
186
+ int main(int argc, char *argv[]){
187
+ QCoreApplication app(argc, argv);
188
+
189
+ QThreadPool *threadPool = QThreadPool::globalInstance();
190
+
191
+ // 线程池最大线程数
192
+ qDebug()<< threadPool->maxThreadCount();
193
+
194
+ for (int i = 0; i < 10; ++i) {
195
+ MyTask *task = new MyTask{};
196
+ threadPool->start(task);
197
+ }
198
+ // 当前活跃线程数 10
199
+ qDebug()<<threadPool->activeThreadCount();
200
+
201
+ app.exec();
202
+ }
203
+ ```
204
+
205
+ 与 ` Asio.thread_pool ` 不同,` QThreadPool ` 采用单例模式,通过静态成员函数 ` QThreadPool::globalInstance() ` 获取对象实例。默认情况下,` QThreadPool ` 线程池的最大线程数为当前硬件支持的并发线程数,例如在我的硬件上为 ` 20 ` ,这点也和 ` Asio.thread_pool ` 不同。
206
+
207
+ ` QThreadPool ` 依赖于 Qt 的事件循环,因此我们使用了 ` QCoreApplication ` 。
208
+
209
+ 而将任务添加到线程池中的做法非常古老原始,我们需要** 自定义一个类型继承并重写虚函数 ` run ` ** ,创建任务对象,然后将任务对象传递给线程池的 ` start ` 方法。
210
+
211
+ 在 Qt6,引入了一个 [ ` start ` ] ( https://doc.qt.io/qt-6/qthreadpool.html#start-1 ) 的重载版本:
212
+
213
+ ``` cpp
214
+ template <typename Callable, QRunnable::if_callable<Callable>>
215
+ void QThreadPool::start (Callable &&functionToRun, int priority)
216
+ {
217
+ start(QRunnable::create(std::forward<Callable >(functionToRun)), priority);
218
+ }
219
+ ```
220
+
221
+ 它相当于是对[`start` 原始版本](https://doc.qt.io/qt-5/qthreadpool.html#start)的:
222
+
223
+ ```cpp
224
+ void start(QRunnable *runnable, int priority = 0);
225
+ ```
226
+
227
+ > [ 源码] ( https://codebrowser.dev/qt6/qtbase/src/corelib/thread/qthreadpool.cpp.html#_ZN11QThreadPool5startEP9QRunnablei ) 。
228
+
229
+ 进行的一个** 包装** ,以支持任何的[ * 可调用(* Callable* )* ] ( https://zh.cppreference.com/w/cpp/named_req/Callable ) 类型,而无需再繁琐的继承重写 ` run ` 函数。
230
+
231
+ ``` cpp
232
+ threadPool->start ([ =] {
233
+ qDebug()<<QString("thread id %1").arg(i);
234
+ });
235
+ ```
236
+
171
237
## 实现线程池
172
238
173
239
实现一个普通的能够满足日常开发需求的线程池实际上非常简单,也只需要一百多行代码。
0 commit comments