建立网站的信息集成过程,重庆绝美的十大冷门景点,沃航科技网站开发,建阳建设局网站Qt中有多种方法实现多线程#xff1a; QThreadQThreadPool和QPunnable#xff08;重用线程#xff09;Qt ConcurrentWorkerScript#xff08;QML中的线程#xff09;QThread 在上两篇文章中已经解释了#xff0c;这里就不再赘述。 QThreadPoo和QRunnable#xff08;实现…Qt中有多种方法实现多线程 QThreadQThreadPool和QPunnable重用线程Qt ConcurrentWorkerScriptQML中的线程QThread 在上两篇文章中已经解释了这里就不再赘述。 QThreadPoo和QRunnable实现的多线程
QRunnable
QRunnable 类是一个接口用于表示需要执行的任务或代码段由 run 函数的重新实现表示。
autoDelete返回是否自动删除setAutoDelete设置自动删除thue
设置自动删除的话在QThreadPool中会自动删除QRunnable 使用的注意事项 启用自动删除时使用相同的 QRunnable 多次调用 QThreadPoool::start 会产生争用条件不建议这样做。 QRunnable和QThread的区别 QThreadPool线程池
顾名思义是有很多线程的池子 可以管理池子中的线程。 线程池的优点 降低资源消耗。 通过重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度。 当任务到达时任务可以不需要等到线程创建就能立即执行。提高线程的可管理性。 线程是稀缺资源使用线程池可以进行统一的分配、调优和监控。 常用函数 setMaxThreadCount() 设置线程池中最大的线程数默认QThreadidealThreadCountsetExpiryTimeoutint将超时xx毫秒未使用的线程视为已过期并将退出已在运行的线程没有影响。建议在创建线程池后立即设置。setStackSize() 设置线程池工作线程的堆栈大小当线程池创建新线程时使用 默认值为 0clear清除队列中未开启的可运行项globalInstance返回一个全局QThreadPool实例reserveThread保留一个线程 此函数将始终增加活动线程数releaseThread释放reserveThread保留的线程startQRunnable,int开启一个线程,可以设置优先级tryStart尝试开启一个线程tryTake尝试从队列中删除指定的尚未启动的可运行对象谨慎使用waitForDone(int)等待所有线程退出最多毫秒毫秒并从线程池中删除所有线程。如果删除了所有线程返回trueactiveThreadCount当前活跃的线程数
启动QRunnable线程的方法 使用QThreadPool::globalInstance()-start()启动 全局创建一个QThreadPool 对象然后通过该对象启动Runnable类
#ifndef RUNNABLE_H
#define RUNNABLE_H
#includeQThread
#includeQDebug
#includeQRunnableclass Runnable:public QRunnable
{
public:explicit Runnable()//构造函数{}~Runnable()//析构函数{}void run()//重写run函数{qDebug()Runnable中的run函数;qDebug()thread to run():QThread::currentThreadId();}
};
#endif // RUNNABLE_H
1.使用QThreadPool::globalInstance()-start()启动 全局
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);qDebug()主线程号QThread::currentThread();Runnable *ablenew Runnable;QThreadPool::globalInstance()-start(able);} 2.创建一个QThreadPool 对象然后通过该对象启动
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);qDebug()主线程号QThread::currentThread();Runnable *ablenew Runnable;//QThreadPool::globalInstance()-start(able);QThreadPool pool;pool.start(able);} 线程池函数的使用 QThreadPool pool;qDebug()本机的线程数QThread::idealThreadCount();qDebug()线程池中的线程数pool.maxThreadCount();pool.setMaxThreadCount(10);//设置线程池中最大的线程数pool.setExpiryTimeout(40000);//如果线程40000毫秒40秒未使用使它过期Runnable *runnablenew Runnable;pool.reserveThread();//保留一个线程pool.start(runnable);//开启线程qDebug()当前活跃线程数pool.activeThreadCount();pool.releaseThread();//释放那个保留的线程qDebug()当前活跃线程数pool.activeThreadCount();QRunnable释放内存问题 QRunnable可以执行完释放内存需要将autoDelete设置为true默认为true。 #ifndef RUNNABLE_H
#define RUNNABLE_H
#includeQThread
#includeQDebug
#includeQRunnableclass Runnable:public QRunnable
{
public:explicit Runnable()//构造函数{}~Runnable()//析构函数{qDebug()__FUNCTION__;}void run()//重写run函数{qDebug()thread to run():QThread::currentThreadId();}
};
#endif // RUNNABLE_H QThreadPool pool;Runnable *runnablenew Runnable;pool.start(runnable);//开启线程 执行完后自动调用析构函数。 QRunnable的通信问题
由于QRunnable是单独的一个类并没有继承QObject所以没有connect函数所以无法于外界进行通信。
解决该问题的方法 使用QMetaObject::invokeMethod()使用多继承的方式同时继承QRunnable和QObject但这样的话会使接口混乱尽量不要使用QMetaObject::invokeMethod的创建方法
QMetaObjectinvokeMethodQObject *obj //使用的类const char *member //调用函数名QtConnectionType type//调用类型QGenericReturnArgument ret//用来存储返回值的类型QGenericArgument val0 QGenericArgumentnullptrQGenericArgument val1 QGenericArgument QGenericArgument val2 QGenericArgument QGenericArgument val3 QGenericArgumentQGenericArgument val4 QGenericArgumentQGenericArgument val5 QGenericArgumentQGenericArgument val6 QGenericArgument QGenericArgument val7 QGenericArgument QGenericArgument val8 QGenericArgumentQGenericArgument val9 QGenericArgument//最多有10个参数
*obj需要把使用类传进去
member函数的名称
type调用类型 Qt::DirectConnnect 立即调用该成员函数Qt::QueuedConnection 一旦应用程序进入主事件循环就会发送 QEvent 并调用成员。Qt::BlockQueuedConnection 当前线程将阻塞直到事件被传递。使用此连接类型在同一线程中的对象之间进行通信将导致死锁。Qt::AutoConnection 如果 obj 与调用方位于同一线程中则同步调用成员;否则它将异步调用该成员。val0-val9最多可以有10个参数
传参的方式使用宏传参 Q_ARG(typeconst Typevalue)Q_RETURN_ARG(type, Typevalue)QString Shellow;
QMetaObject::invokeMethod(obj, Text,Qt::DirectConnection,Q_ARG(QString,pppp),Q_RETURN_ARG(QString,S));
Runnable函数
#ifndef RUNNABLE_H
#define RUNNABLE_H
#include widget.h
#includeQThread
#includeQObject
#includeQDebug
#includeQRunnable
#includeQMetaObjectclass Runnable:public QRunnable
{
public:explicit Runnable(QObject *obj1):obj(obj1)//构造函数{}~Runnable()//析构函数{}void run()//重写run函数{ QString Shellow;QMetaObject::invokeMethod(obj,Text,Qt::DirectConnection,Q_ARG(QString,pppp),Q_RETURN_ARG(QString,S));qDebug()thread to run():QThread::currentThreadId();}QObject *objnullptr;//需要传的对象
};
#endif // RUNNABLE_H
主函数 主类中创建函数开头需要添加Q_INVOKABLE这样才直到调用哪一个函数 #include widget.h
#include ui_widget.h
#includerunnable.h
#includeQThreadPool
class Rnnable;
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);QThreadPool pool;Runnable *runnablenew Runnable(this);//传入调用的对象pool.start(runnable);//开启线程
}
Q_INVOKABLE void Widget::Text(QString a,QString b)//创建一个函数名称要相同
{qDebug()a;qDebug()b;
}
Widget::~Widget()
{delete ui;
} Qt Concurrent并发
QtConcurrent命名空间提供高级 API可以在不使用互斥锁、读写锁、等待条件或信号量等低级线程原语的情况下编写多线程程序。
使用 QtConcurrent编写的程序会根据可用的处理器内核数量自动调整使用的线程数。这意味着编写的应用程序在部署到多核系统时将自动扩展。
如何使用Qt Concurrent:
1.pro文件中添加 QT concurrent 2. 添加头文件 #includeQtConcurrent 以下是如何执行QtConcurrent的使用方法 使用QtConcurrent::run函数执行内容 函数模型
//T为模板类型QFutureT QtConCurrent::run(Function)//执行一个函数QFutureT QtConCurrent::run(threadpoolFunction)//线程池中取出线程执行function函数
执行一个函数
void text()
{qDebug()ok;
}
void text1(int a)
{qDebug()a;
}
void text2(QString s1,QString s2)
{qDebug()s1s2;
}
int main(int argc, char *argv[])
{QApplication a(argc, argv);QFuturevoid fuQtConcurrent::run(text);QFuturevoid fu1QtConcurrent::run(text1,10);QFuturevoid fu2QtConcurrent::run(text2,QString(aa),QString(bb));fu.waitForFinished();//等待完成fu1.waitForFinished();//等待完成fu2.waitForFinished();//等待完成return a.exec();
}通过线程池中的进程执行函数
void text1(int a)
{qDebug()a;
}int main(int argc, char *argv[])
{QApplication a(argc, argv);QThreadPool pool;QFuturevoid fuQtConcurrent::run(pool,text1,10);fu.waitForFinished();//等待完成return a.exec();
} 3.调用常量成员函数 run函数可以接收成员函数的指针第一个参数必须是常量引用或指向类实例的指针。 QByteArray bytearray hello world;
QFutureQListQByteArray future QtConcurrent::run(bytearray, QByteArray::split, ,);
QListQByteArray result future.result();4.调用非常量成员函数
QImage image ...;
QFuturevoid future QtConcurrent::run(image, QImage::invertPixels,QImage::InvertRgba);
future.waitForFinished(); 总结以上三种多线程的特点
特征QThreadQRunnable和QThreadPoolQtConcurrent::run() QtConcurrent MapFilterReduce 指定优先级是是 可运行 事件循环 是 线程可以通过 信号接收数据更新 是 可以使用 信号控制螺纹 是是QFutureWatcher) 可以通过 QFuture监控线程 部分是是 内置暂停/ 恢复/取消功能 是
适用场景
生命周期开发任务解决方案持续运行在另一个线程中重复执行昂贵的操作其中线程不需要接收任何信号或事件。直接在QThreadrun()的重新实现中编写无限循环。在没有事件循环的情况下启动线程。让线程发出信号以将数据发送回 GUI 线程。持续运行让一个对象存在于另一个线程中该线程可以根据请求执行不同的任务和/或可以接收要使用的新数据。子类 一个QObject 以创建工作线程。实例化此工作线程对象和 QThread。将工作线程移动到新线程。通过排队的信号槽连接将命令或数据发送到工作器对象。一次调用在另一个线程中运行新的线性函数可以选择在运行期间更新进度。Qt提供不同的解决方案 将函数放在 QThreadrun 的重新实现中并启动 Qthread。发出信号以更新进度。或将函数放在 QRunnablerun 的重新实现中并将 QRunnable 添加到 QthreadPool 中。写入线程安全变量以更新进度。或使用 Q他Concurrent 运行函数。写入线程安全变量以更新进度。一次调用在另一个线程中运行现有函数并获取其返回值。使用 QtConcurrentrun 运行函数。让 QFutureWatcher 在函数返回时发出 done 信号并调用 QFutureWatcherresult 来获取函数的返回值。一次调用使用所有可用核心对容器的所有项执行操作。例如从图像列表生成缩略图。 使用 Qt Concurrent 的 QtConcurrentfilter 函数选择容器元素使用 QtConcurrentmap 函数对每个元素应用操作。要将输出折叠成单个结果请改用 QtConcurrentfilteredReduction 和 QtConcurrent::mappedReduction。 参考文章
Thread Support in Qt | Qt 5.15 Qt线程之QRunnable的使用详解_luoyayun361的博客-CSDN博客_qrunnable
【QT】继承QRunnableQThreadPool实现多线程_李春港的博客-CSDN博客_继承qrunnable
Qt并发模块Qt Concurrent的使用_Amnesia Greens的博客-CSDN博客_qtconcurrent