Qt线程池


1、线程池是什么?

线程池是一种线程使用模式,它管理着一组可重用的线程,可以处理分配过来的可并发执行的任务。
线程池设有最大线程数,可以避免线程数过多会导致额外的线程切换开销。
线程池管理的线程具有可重用性,可以减少创建和销毁线程的次数。
它的主要目的是减少程序员编写的重复代码,提高程序的效率和性能,在高并发的项目中会用到,比如node.js有很多异步操作,底层就是用线程池来处理的。

2、Qt线程池

Qt提供了线程池类QThreadPool,可以帮助减少使用线程的程序中的线程创建成本。

2.1、用法

每个Qt应用程序都有一个全局QThreadPool对象,可以通过调用globalInstance()来访问该对象。
想让线程池执行任务,需要创建一个QRunable的子类并且实现run()虚函数,然后将这个子类的对象传递到QThreadPool的start()方法。

例程

下面的例子是用一个最大线程数为3的线程池,打印十次aaa,每打印一次耗时500ms。

#include <QThreadPool>
#include <QDebug>

class PrintA : public QRunnable
{
    
    
    virtual void run() override {
    
    
        QThread::msleep(500);
        qDebug() << "aaa " << QThread::currentThreadId();
    }
};

int main(int argc, char *argv[])
{
    
    
    auto pool = QThreadPool::globalInstance();
    pool->setMaxThreadCount(3);     //设置线程池最多3个线程

    PrintA *printer = new PrintA;
    printer->setAutoDelete(false);  //执行后不自动释放,因为要重复使用

    /* 打印十次 */
    for (int i = 0; i < 10; i++) {
    
    
        pool->start(printer);
    }

    pool->waitForDone();            //等待执行完毕

    delete printer;
}

输出。
在这里插入图片描述
打印是乱序的,符合并发的特点。一共出现了3个线程Id,也符合设置的最大线程数。

2.2、线程池对性能的提升

2.3、运行算法

例:有一个字符串string,由0和1组成,长度为10000000 * 10,需要统计里面1的个数。

单线程写法
#include <QDebug>
#include <QElapsedTimer>

int main(int argc, char *argv[])
{
    
    
    QString string;
    string = "1000101010";
    string = string.repeated(10000000);
    int count = 0;

    QElapsedTimer timer;
    timer.start();

    for (int i = 0, len = string.length(); i < len; ++i) {
    
    
        if (string[i] == '1') {
    
    
            count++;
        }
    }
    
    qDebug() << "spend time: " << timer.elapsed() << "ms, count: " << count;
}

在这里插入图片描述
总共耗时2843毫秒。

线程池写法

思路:把string分割成100块,用多线程分别计算。

#include <QThreadPool>
#include <QDebug>
#include <QElapsedTimer>
#include <QMutex>

class Counter : public QRunnable
{
    
    
public:
    Counter(int index, int len, QString *string, QMutex *mutex, int *count) {
    
    
        m_index = index;
        m_length = len;
        m_string = string;
        m_mutex = mutex;
        m_count = count;
    }

private:
    void run() {
    
    
        int count = 0;
        for (int i = m_index, end = m_index + m_length; i < end; ++i) {
    
    
            if ((*m_string)[i] == '1') {
    
    
                count++;
            }
        }
		/* 多线程操作共享变量需要加锁 */
        m_mutex->lock();
        *m_count += count;
        m_mutex->unlock();
    }

    int m_index;
    int m_length;
    QString *m_string;4
    QMutex *m_mutex;
    int *m_count;

};

int main(int argc, char *argv[])
{
    
    
    QString string;
    string = "1000101010";
    string = string.repeated(10000000);
    int count = 0;

    QElapsedTimer timer;
    timer.start();

    auto pool = QThreadPool::globalInstance();
    pool->setMaxThreadCount(8);					//设置最多8个线程

	QMutex mutex;
	/* 分割成100块,分别计算 */
    for (int i = 0, span = string.length() / 100; i < 100; i++) {
    
    
        Counter *a = new Counter(i * span, span, &string, &mutex, &count);
        a->setAutoDelete(true);	//执行完后自动释放
        pool->start(a);
    }
    pool->waitForDone();

    qDebug() << "spend time: " << timer.elapsed() << "ms, count: " << count;
}

在这里插入图片描述
总共耗时712ms,在本例中,效率是单线程的4倍。

猜你喜欢

转载自blog.csdn.net/weixin_45001971/article/details/129087323