Пул потоков Qt


1. Что такое пул потоков?

Пул потоков — это модель использования потоков, которая управляет группой повторно используемых потоков, которые могут обрабатывать назначенные задачи, которые могут выполняться одновременно.
Пул потоков имеет максимальное количество потоков, чтобы избежать дополнительных затрат на переключение потоков, вызванных слишком большим количеством потоков.
Потоки, управляемые пулом потоков, можно использовать повторно, что позволяет сократить количество создания и уничтожения потоков.
Его основная цель — сократить повторяющийся код, написанный программистами, и повысить эффективность и производительность программы. Он будет использоваться в проектах с высоким уровнем параллелизма. Например, node.js имеет множество асинхронных операций, а нижний уровень обрабатывается пул потоков.

2. Пул потоков Qt

Qt предоставляет класс пула потоков QThreadPool, который может помочь снизить затраты на создание потоков в программах, использующих потоки.

2.1. Использование

Каждое приложение Qt имеет глобальный объект QThreadPool, доступ к которому можно получить, вызвав globalInstance().
Если вы хотите, чтобы пул потоков выполнял задачи, вам необходимо создать подкласс QRunable и реализовать виртуальную функцию run(), а затем передать объект этого подкласса методу start() QThreadPool.

рутина

В следующем примере используется пул потоков с максимальным количеством потоков 3 для печати aaa десять раз, и каждая печать занимает 500 мс.

#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 идентификатора потока, что также соответствует установленному максимальному количеству потоков.

2.2. Улучшение производительности пула потоков

2.3 Алгоритм запуска

Пример: Имеется строка, состоящая из 0 и 1, длиной 10000000*10. В ней необходимо посчитать количество единиц.

написание одного потока
#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 миллисекунды.

Метод записи пула потоков

Идея: разделить строку на 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;
}

Вставьте сюда описание изображения
Всего это занимает 712 мс. В этом случае эффективность в 4 раза выше, чем у одного потока.

Supongo que te gusta

Origin blog.csdn.net/weixin_45001971/article/details/129087323
Recomendado
Clasificación