C++11消息隊列 + Qt線程池 + QRunnable執行任務簡單模型

一、模板類queue,包含頭文件<queue>中,是一個FIFO隊列。ios

queue.push():在隊列尾巴增長數據
queue.pop():移除隊列頭部數據
queue.font():獲取隊列頭部數據的引用
...

二、Qt庫的線程池,QThreadPool安全

QThreadPool.setMaxThreadCount():設置線程池最大線程數
QThreadPool.start(new QRunnable(..)):開啓線程池調用QRunnable

三、QRunnable執行任務函數

void run();//重寫虛函數,在裏面消費任務隊列
setAutoDelete(true)//默認就是true,消費結束自動回收內存

四、代碼this

run.hspa

#ifndef RUN_H
#define RUN_H

#include <QObject>
#include <QRunnable>
#include <string>
#include <iostream>

struct MyString
{
    std::string valueStr;
};

class Run : public QObject , public QRunnable
{
    Q_OBJECT
public:
    Run() = default;
    Run(const MyString& myString);
protected:
    ~Run() = default;
    void run();
signals:

public slots:

private:
    MyString myString;
};

#endif // RUN_H

說明:
MyString結構體代替實際項目中的任務,Run接口的run純虛函數用來消費分配來的MyString
run.cpp
#include "run.h"
#include <QThread>
#include <QDebug>
Run::Run(const MyString &myString)
{
    this->myString = myString;
    //this->setAutoDelete(true);//默認就是true
}

void Run::run()
{
    //std::cout << "value:" << this->myString.valueStr <<";調用線程ID爲:" << QThread::currentThread() << std::endl;
    qDebug() << "value:" << QString::fromStdString(myString.valueStr) << "thread:" << QThread::currentThreadId();
    QThread::msleep(100);
}
說明:不使用cout打印是由於,cout打印不是原子操做,可能多個字符串被雜糅在一塊兒打印;qDebug不會,應該底層加了鎖

main.cpp線程

#include <QCoreApplication>
#include "run.h"
#include <queue>
#include <mutex>
#include <QThreadPool>
#include <thread>
using namespace std;
queue<MyString> myList;
mutex myMutex;
volatile bool addThreadIsEnd = false;
void makeListThread();
int main(int argc, char *argv[])
{   
    QCoreApplication a(argc, argv);
    cout << "begin main" << endl;
    thread addThread(makeListThread);
    addThread.detach();
    cout << "begin addThread" << endl;
    QThreadPool tp;
    tp.setMaxThreadCount(20);
    cout << "begin threadPool" << endl;
    while(true)
    {
        if(!myList.empty())
        {
            MyString tempMyString = myList.front();
            tp.start(new Run(tempMyString));
            myMutex.lock();
            myList.pop();
            myMutex.unlock();
        }
        else
        {
            if(addThreadIsEnd)
            {
                break;
            }
            else
            {
                QThread::msleep(10);
            }
        }
    }
    cout << "end main,list size:" << myList.size() << endl;
    return a.exec();
}

void makeListThread()
{
    string a;
    MyString tempMyString;
    for(int i=0;i<10000;i++)
    {
        QThread::msleep(0);
        a = to_string(i);
        tempMyString.valueStr = a;
        myMutex.lock();
        myList.push(tempMyString);
        myMutex.unlock();
    }
    addThreadIsEnd = true;
    cout << "end addThread" << endl;
}
五、模型

 六、其餘說明指針

6.一、假設線程池大小有n個,那麼這n個線程在線程池初始化的時候就已經定了,即n個線程id是恆定的,隊列永遠由這n個線程消費code

6.二、std::queue非線程安全,同時往隊列加任務、取任務可能會觸發線程安全問題;同時刪除頭任務、訪問頭任務也可能會觸發線程安全問題,須要加線程鎖對象

6.三、tp.start(new Run(tempMyString));這裏new了一個沒有指針指向的Runnable對象,在哪裏回收的呢?Run.setAutoDelete(true)自動回收blog

相關文章
相關標籤/搜索