QT-线程池

        在程序逻辑中经常会碰到需要处理大批量任务的情况,比如密集的网络请求,或者日志分析等等。一般会创建一个队列,用一个或者多个线程去消费这个队列,一般也要处理队列的加锁和解锁的问题,除非在设计时就能够做到专列专用,否则锁是不可避免的。而且在入队和出队的操作上肯定还是要加锁,因为他们是在不同线程对同一个资源进行操作。

        线程池就是为这个而设计的,比如

        Windows自带的线程池:   CreateThreadpoolWork  SubmitThreadpoolWork

        boost的线程池: io_service std::thread, 由io_service来调度线程

        QT: QThreadPool

这里说QThreadPool, 最简单的创建线程池的方法,就是创建一个QThreadPool对象,然后调用start将继承自QRunnable的任务对象传入,这样任务对象就被放入了线程池的队列中。实现任务方法,需要继承QRunnable并重写run方法,线程池会调用这个方法来执行。

我们也可以调用QthreadPool::setMaxThreadCount来设定线程池的最大线程数,默认是同CPU核心数相同。

这里要注意继承自QRunnable生命周期如果没有被管理起来,想要在执行完成后自动释放,那就需要Qrunnable::setAutoDelete(true),在执行完成后会自动释放掉任务对象。

对于普通的任务消费,这几个接口完全够用了,QT还有一个更简易的用于执行任务的方法:

QtConcurrent::run这个方法其实也是将任务放入了一个线程池中去处理,观察一下他的接口:

QFuture QtConcurrent::run(Function function, ...)

QFuture QtConcurrent::run(QThreadPool *pool, Function function, ...)

第一个接口只需要一个function,文档上说这个接口等价于:

QtConcurrent::run(QThreadPool::globalInstance(), function, ...);

所以这个方法默认将任务放入了全局线程池,那么这个任务的执行的时机就会受到其他放入全局线程池任务的多少和时间决定了,所以如果是紧急的任务,最好使用第二个接口,自己创建一个专用线程池,将任务交给这个专用线程池去处理。

总的来讲,线程池的思路大多相同,都是管理一个公共队列,然后开启多个线程去消费,不同之处可能在于线程调度的算法不同。有的线程池会检测线程池中的任务量来决定是否要增加新线程,根据空闲时间来决定是否减少线程。有的线程池对任务增加了优先级,可以让优先级高的任务先得以执行。

你可能感兴趣的:(C++,QT)