El uso del grupo de subprocesos en Qt

1. El principio del grupo de subprocesos

Cuando usamos subprocesos, creamos un subproceso, que es muy simple de implementar, pero habrá un problema: si hay una gran cantidad de subprocesos concurrentes, y cada subproceso finaliza después de ejecutar una tarea corta, por lo que la creación frecuente de subprocesos será en gran medida reducir la eficiencia del sistema, porque la creación y destrucción frecuente de subprocesos lleva tiempo.

Entonces, ¿hay alguna manera de hacer que los hilos sean reutilizables, es decir, después de ejecutar una tarea, no se destruye, pero puede continuar ejecutando otras tareas?

Un grupo de subprocesos es una forma de multiproceso en el que las tareas se agregan a una cola y luego se inician automáticamente después de que se crean los subprocesos. Los subprocesos del grupo de subprocesos son todos subprocesos de fondo. Cada subproceso utiliza el tamaño de pila predeterminado, se ejecuta con la prioridad predeterminada y se encuentra en un apartamento de subprocesos múltiples. Si un subproceso está inactivo en el código administrado (como esperando un evento), el grupo de subprocesos insertará otro subproceso de trabajo para mantener ocupados a todos los procesadores. Si todos los subprocesos del grupo de subprocesos se mantienen ocupados todo el tiempo, pero la cola contiene trabajo pendiente, el grupo de subprocesos creará otro subproceso de trabajo después de un tiempo, pero la cantidad de subprocesos nunca superará el máximo. Los subprocesos que excedan el máximo se pueden poner en cola, pero no comenzarán hasta que otros subprocesos hayan terminado.

Existe un concepto de grupo de subprocesos en cada lenguaje de programación, y muchos lenguajes proporcionan directamente un grupo de subprocesos, que se puede usar directamente como programador. Permítanme presentar el principio de implementación del grupo de subprocesos: los componentes principales del grupo de subprocesos están
divididos en tres partes, y estas tres partes pueden trabajar juntas para obtener un grupo de subprocesos completo:

  1. La cola de tareas almacena las tareas que deben procesarse y estas tareas son procesadas por los subprocesos de trabajo.
  • A través de las funciones de API proporcionadas por el grupo de subprocesos, agregue una tarea pendiente a la cola de tareas o elimínela de la cola de tareas.
  • Las tareas procesadas se eliminan de la cola de tareas
  • El usuario del grupo de subprocesos, es decir, el subproceso que llama a la función del grupo de subprocesos para agregar tareas a la cola de tareas, es el subproceso productor.
  1. Subprocesos de trabajo (consumidores de tareas de la cola de tareas), N
  • En el grupo de subprocesos se mantiene un cierto número de subprocesos de trabajo cuya función es leer la cola de tareas de forma continua, sacar tareas de ella y procesarlas.
  • El subproceso de trabajo es equivalente al rol de consumidor de la cola de tareas.
  • Si la cola de tareas está vacía, el subproceso de trabajo se bloqueará (mediante el bloqueo de variable de condición/semáforo)
  • Si hay una nueva tarea después del bloqueo, el productor desbloqueará y el subproceso de trabajo comenzará a funcionar
  1. Subproceso de administrador (no procesa tareas en la cola de tareas), 1
  • Su tarea es detectar periódicamente la cantidad de tareas en la cola de tareas y la cantidad de subprocesos de trabajo en un estado ocupado
  • Cuando hay demasiadas tareas, se pueden crear algunos subprocesos de trabajo nuevos de manera adecuada
  • Cuando hay muy pocas tareas, algunos subprocesos de trabajo pueden destruirse correctamente
    inserte la descripción de la imagen aquí

2. QR ejecutable

Para usar el grupo de subprocesos en Qt, primero debe crear una tarea, y cada tarea agregada al grupo de subprocesos debe ser del tipo QRunnable, por lo que debe crear una subclase en el programa para heredar la clase QRunnable y luego reescribir el método run(), en este Escriba la tarea que se ejecutará en el grupo de subprocesos en la función, y pase este objeto de subclase al grupo de subprocesos, para que la tarea pueda ser procesada por un subproceso de trabajo en el grupo de subprocesos.
No hay muchas funciones de uso común de la clase QRunnable, principalmente para establecer si el objeto de la tarea debe destruirse automáticamente después de pasar al grupo de subprocesos.

// 在子类中必须要重写的函数, 里边是任务的处理流程
[pure virtual] void QRunnable::run();

// 参数设置为 true: 这个任务对象在线程池中的线程中处理完毕, 这个任务对象就会自动销毁
// 参数设置为 false: 这个任务对象在线程池中的线程中处理完毕, 对象需要程序猿手动销毁
void QRunnable::setAutoDelete(bool autoDelete);
// 获取当前任务对象的析构方式,返回true->自动析构, 返回false->手动析构
bool QRunnable::autoDelete() const;

Cree una clase de tarea para agregarla al grupo de subprocesos de la siguiente manera:

class MyWork : public QObject, public QRunnable
{
    
    
    Q_OBJECT
public:
    explicit MyWork(QObject *parent = nullptr)
    {
    
    
        // 任务执行完毕,该对象自动销毁
        setAutoDelete(true);
    }
    ~MyWork();

    void run() override{
    
    }
}

En el ejemplo anterior, la clase MyWork es una herencia múltiple. Si necesita usar el mecanismo de ranura de señal de Qt para la transferencia de datos en esta tarea, debe heredar la clase QObject. Si no usa ranuras de señal para transferir datos, puede no lo herede, simplemente herede QRunnable.

class MyWork :public QRunnable
{
    
    
    Q_OBJECT
public:
    explicit MyWork()
    {
    
    
        // 任务执行完毕,该对象自动销毁
        setAutoDelete(true);
    }
    ~MyWork();

    void run() override{
    
    }
}

3. Grupo de subprocesos Q

La clase QThreadPool en Qt administra un grupo de QThreads y mantiene una cola de tareas dentro. QThreadPool administra y recicla objetos QThread individuales para ayudar a reducir los costos de creación de subprocesos en programas que usan subprocesos. Cada aplicación Qt tiene un objeto QThreadPool global al que se puede acceder llamando a globalInstance(). También puede crear un objeto QThreadPool por separado.
Las funciones API comúnmente utilizadas del grupo de subprocesos son las siguientes:

// 获取和设置线程中的最大线程个数
int maxThreadCount() const;
void setMaxThreadCount(int maxThreadCount);

// 给线程池添加任务, 任务是一个 QRunnable 类型的对象
// 如果线程池中没有空闲的线程了, 任务会放到任务队列中, 等待线程处理
void QThreadPool::start(QRunnable * runnable, int priority = 0);
// 如果线程池中没有空闲的线程了, 直接返回值, 任务添加失败, 任务不会添加到任务队列中
bool QThreadPool::tryStart(QRunnable * runnable);

// 线程池中被激活的线程的个数(正在工作的线程个数)
int QThreadPool::activeThreadCount() const;

// 尝试性的将某一个任务从线程池的任务队列中删除, 如果任务已经开始执行就无法删除了
bool QThreadPool::tryTake(QRunnable *runnable);
// 将线程池中的任务队列里边没有开始处理的所有任务删除, 如果已经开始处理了就无法通过该函数删除了
void QThreadPool::clear();

// 在每个Qt应用程序中都有一个全局的线程池对象, 通过这个函数直接访问这个对象
static QThreadPool * QThreadPool::globalInstance();

En general, no necesitamos crear un objeto de grupo de subprocesos en el programa Qt, solo use el objeto global de grupo de subprocesos proporcionado por Qt para cada aplicación directamente. Después de obtener el objeto del grupo de subprocesos, llame al método start() para agregar una tarea al grupo de subprocesos, y esta tarea puede ser procesada por el grupo de subprocesos dentro del grupo de subprocesos.Usar el grupo de subprocesos es mucho más que crear subprocesos por sí mismo. El enfoque de subprocesamiento es más simple y más fácil de mantener.

El uso específico es el siguiente:

mitrabajo.h

class MyWork :public QRunnable
{
    
    
    Q_OBJECT
public:
    explicit MyWork();
    ~MyWork();

    void run() override;
}

mitrabajo.cpp

MyWork::MyWork() : QRunnable()
{
    
    
    // 任务执行完毕,该对象自动销毁
    setAutoDelete(true);
}
void MyWork::run()
{
    
    
    // 业务处理代码
    ......
}

ventanaprincipal.cpp

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    
    
    ui->setupUi(this);

    // 线程池初始化,设置最大线程池数
    QThreadPool::globalInstance()->setMaxThreadCount(4);
    // 添加任务
    MyWork* task = new MyWork;
    QThreadPool::globalInstance()->start(task);    
}

Supongo que te gusta

Origin blog.csdn.net/houxian1103/article/details/131438335
Recomendado
Clasificación