Qt线程池坑点

13 篇文章 0 订阅

近日自己写的一个小工具,用到了Qt线程池QThreadPool和Redis,从QRunnable继承实现了一个Executor,Redis连接由一个自定义的Manager管理,根据当前所处的线程,自动创建连接,连接创建后缓存在Manager中,下次相同的线程再执行任务时,使用之前创建的Redis连接进行操作。

使用中有时会出现Redis连接发出数据后,收不到回复的情况,多次试验后发现如果执行一次后,经过30秒以上再执行,就会出现这个问题,30秒以内再次执行则没这个问题。

排查过程如下:

1.先是怀疑是socket的问题,但是抓包后发现socket数据已经返回了,只是应用没有收到数据。

2.跟踪Qt源码后发现,是系统没给程序发送读数据的消息,正常情况,发送数据会收到一个socket写数据消息,收到数据后会收到一个socket读数据消息,异常时只有写数据消息,没有读数据消息,为啥没消息卡了好长时间。

3.自己new了一个Thread,调用Executor,发现只能执行一次,第二次再执行就无法收到数据,与时间无关,跟踪源码发现Qt的线程每次start都会重新创建一个系统原生线程,但是socket是在第一个执行时创建的,也就是说创建socket的系统线程在第一次执行完后就销毁了,后面再执行时的系统线程不是创建socket的系统线程,估计就是因为线程不同导致系统消息没发送到应用中,但是为什么写数据的消息能收到,不太清楚。

4.查看QThreadPool代码,和推断的的一致,一个线程空闲超过30秒时,ThreadPool会将系统线程释放,只保留QThread对象,再次使用该QThread时会重新创建系统线程,其中30秒的超时时间可以通过setExpiryTimeout函数进行设置,设置值小于0时,始终不会释放系统线程,直到QThread被释放。

综上,如果线程中用到的资源不是每次都重新创建,则需要注意其生命周期,注意是否会因为系统线程的释放导致异常结果。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt 线程池是一种用于管理多线程任务的工具。它可以在程序中创建一组线程,并将任务分配给这些线程,以实现并发执行任务的效果,从而提高程序的性能和响应速度。 使用 Qt 线程池,需要先创建一个 QThreadPool 对象,并设置最大线程数。然后,将任务封装成 QRunnable 对象,并通过 QThreadPool::start() 函数将任务提交给线程池线程池会自动管理线程的创建和销毁,以及任务的调度和执行。 下面是一个简单的示例代码,演示了如何使用 Qt 线程池: ```c++ #include <QCoreApplication> #include <QThreadPool> #include <QDebug> class MyTask : public QRunnable { public: MyTask(int id) : m_id(id) {} void run() override { qDebug() << "Task" << m_id << "is running on" << QThread::currentThread(); } private: int m_id; }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QThreadPool threadPool; threadPool.setMaxThreadCount(4); for (int i = 0; i < 10; i++) { MyTask *task = new MyTask(i); threadPool.start(task); } threadPool.waitForDone(); qDebug() << "All tasks are done."; return a.exec(); } ``` 在这个示例中,我们创建了一个包含 4 个线程的线程池,然后提交了 10 个任务,每个任务都会打印自己的编号和运行线程的编号。最后,我们调用了 QThreadPool::waitForDone() 函数,等待所有任务完成,并输出 "All tasks are done." 消息。 需要注意的是,Qt 线程池只适用于短时间执行的任务,不适合长时间执行的任务。长时间执行的任务需要使用 QThread 或者自定义线程,以避免阻塞线程池
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值