• C++11消息队列 + Qt线程池 + QRunnable执行任务简单模型


    1、模板类queue,包含头文件<queue>中,是一个FIFO队列。

    queue.push():在队列尾巴增加数据
    queue.pop():移除队列头部数据
    queue.font():获取队列头部数据的引用
    ...

    2、Qt库的线程池,QThreadPool

    QThreadPool.setMaxThreadCount():设置线程池最大线程数
    QThreadPool.start(new QRunnable(..)):开启线程池调用QRunnable

    3、QRunnable执行任务

    void run();//重写虚函数,在里面消费任务队列
    setAutoDelete(true)//默认就是true,消费结束自动回收内存

    4、代码

    run.h

    #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;
    }
    5、模型

     6、其他说明

    6.1、假设线程池大小有n个,那么这n个线程在线程池初始化的时候就已经定了,即n个线程id是恒定的,队列永远由这n个线程消费

    6.2、std::queue非线程安全,同时往队列加任务、取任务可能会触发线程安全问题;同时删除头任务、访问头任务也可能会触发线程安全问题,需要加线程锁

    6.3、tp.start(new Run(tempMyString));这里new了一个没有指针指向的Runnable对象,在哪里回收的呢?Run.setAutoDelete(true)自动回收

     
  • 相关阅读:
    Windows Mobile开发资源列表
    Windows Mobile获取SIM卡上的所有电话号码
    Windows Mobile手机软件安装卸载方法
    Windows CE跨进程内存注入之原理
    推荐几篇关于Windows Mobile程序安装包制作的文章
    C#智能设备中程序的调用
    Windows Mobile 获得 MAC,IP,IMEI,IMSI
    为什么要使用Base64?
    如何选择正确的SQL Server Compact安装包
    [Drupal] Using the Administrator theme whenever you want.
  • 原文地址:https://www.cnblogs.com/judes/p/11013450.html
Copyright © 2020-2023  润新知