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)自动回收

 

原文地址:https://www.cnblogs.com/judes/p/11013450.html

时间: 2024-10-12 16:42:52

C++11消息队列 + Qt线程池 + QRunnable执行任务简单模型的相关文章

43_2013年11月22日 线程池 Socket(Thread Lock Process 摇奖 线程池ThreadPool)

1>模拟线程池,生产者消费者问题 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Product { class Program { static void Main(string[] args) { //创建一个池子 MyConncetion[]

【详解】消息队列和线程关系

1.进程-线程-消息队列 简单的来说,什么是进程?什么是线程?打个比方,你的程序要执行,操作系统就会把你的exe文件加载到内存中,那就生成一个进程了(当然还包含分配到的资源等):对于线程,你可以理解成是一个程序里的不同部分,这有点类似函数,所不同的是各个线程是同时执行的. 例如,你的主线程创建了另一个副线程,那么这两个线程是同时在工作的,不存在调用 - 返回的概念. 一个进程里可以有多个线程在执行,称为执行实例. shining:因为线程的资源是从进程资源中分配出来的,因此同一个进程中的多个线程

基于队列的线程池

import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /**  * Created 

线程进阶之线程队列、线程池和协程

本节目录: 1.线程队列 2.线程池 3.协程 一.线程队列 线程之间的通信我们列表行不行呢,当然行,那么队列和列表有什么区别呢? queue队列 :使用import queue,用法与进程Queue一样 queue is especially useful in threaded programming when information must be exchanged safely between multiple threads. class queue.Queue(maxsize=0)

阻塞队列和线程池

一.阻塞队列 1.介绍阻塞队列会对当前线程产生阻塞,比如一个线程从一个空的阻塞队列中取元素,此时线程会被阻塞直到阻塞队列中有了元素.当队列中有元素后,被阻塞的线程会自动被唤醒(不需要我们编写代码去唤醒). 2.实现ArrayBlockingQueue:基于数组实现的一个阻塞队列,在创建ArrayBlockingQueue对象时必须制定容量大小.并且可以指定公平性与非公平性,默认情况下为非公平的,即不保证等待时间最长的队列最优先能够访问队列.LinkedBlockingQueue:基于链表实现的一

Java实现锁、公平锁、读写锁、信号量、阻塞队列、线程池等常用并发工具

锁的实现 锁的实现其实很简单,主要使用Java中synchronized关键字. public class Lock { private volatile boolean isLocked = false; private Thread lockingThread = null; public synchronized void lock() throws InterruptedExpection { while(isLocked){ wait(); } isLocked = true; loc

线程池的执行流程

合理使用线程池能够带来3个好处: 1)降低资源消耗:2)提高响应速度:3)提高线程的可管理性. 那么线程池是如何工作的呢,借用并发编程艺术一书中的话来描述当一个任务提交给线程池之后,线程池会怎么做? 首先,线程池会判断核心线程池里的线程(线程总数是30,则coreSize有可能是10)是否都在执行任务.如果没有比方说当前只有9个线程在工作,则从核心线程池中创建一个新的线程来执行任务.如果当前已经有10个线程在工作了,则进入下一步: 其次,线程池会判断工作队列是否已经满了,如果工作队列没有满,则将

QT 线程池 + TCP 小试(一)线程池的简单实现

*免分资源链接点击打开链接http://download.csdn.net/detail/goldenhawking/4492378 很久以前做过ACE + MFC/QT 的中轻量级线程池应用,大概就是利用线程池执行客户机上的运算需求,将结果返回.ACE是跨平台重量级的通信中间件,与常见的应用程序框架需要精心契合,才能不出问题.最近想到既然QT框架本身就已经具有各类功能,何不玩一玩呢,那就开搞!这个实验的代码可以从我的资源内下载. 第一步打算实现的模式,我们需要一个设置为CPU核心数的线程池,这

C++11 —— 使用 thread 实现线程池

1. 引言 在新的 C++11 标准中,引入并发编程的一些基础组件:线程(thread).互斥锁(mutex).条件变量(condition_variable) 等,凭借这些,就足够我设计一个平台无关的 线程池 组件了.下面就详细介绍一下这个线程池组件. 2. 结构设计图 需要特别说明的是,这个线程池组件,在增加了"存在关联性的任务对象顺序执行"的功能后,原本的任务队列就分成了两级任务队列,目的是为了降低 "任务提交" 与 "任务提取" 之间(属