Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3e88f47

Browse files
committed
增加线程池的内容,对 QThreadPool 进行使用介绍 Mq-b#12
1 parent 302a53b commit 3e88f47

File tree

1 file changed

+67
-1
lines changed

1 file changed

+67
-1
lines changed

‎md/详细分析/04线程池.md

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ int main() {
113113
114114
> [运行](https://godbolt.org/z/h5G5hTT4a)测试。
115115
116-
117116
- 创建线程池时,指定线程数量,线程池会创建对应数量的线程。
118117
119118
- 使用 `boost::asio::post` 提交任务,任务会被添加到任务队列中。
@@ -168,6 +167,73 @@ boost::asio::post(pool, task); // 将任务加入线程池
168167
pool.join(); // 等待任务完成 (或者析构自动调用)
169168
```
170169
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+
171237
## 实现线程池
172238
173239
实现一个普通的能够满足日常开发需求的线程池实际上非常简单,也只需要一百多行代码。

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /