当前位置: 首页 > news >正文

海宁网站设计好看的手机网站布局

海宁网站设计,好看的手机网站布局,wordpress书籍推荐,立方集团 网站多线程编程#xff08;二#xff09; ③线程池 Qt中线程池的使用 | 爱编程的大丙 1线程池 我们使用线程的时候就去创建一个线程#xff0c;这样实现起来非常简便#xff0c;但是就会有一个问题#xff1a;如果并发的线程数量很多#xff0c;并且每个线程都是执行…多线程编程二  ③线程池 Qt中线程池的使用 | 爱编程的大丙 1线程池 我们使用线程的时候就去创建一个线程这样实现起来非常简便但是就会有一个问题如果并发的线程数量很多并且每个线程都是执行一个时间很短的任务就结束了这样频繁创建线程就会大大降低系统的效率因为频繁创建线程和销毁线程需要时间。 那么有没有一种办法使得线程可以复用就是执行完一个任务并不被销毁而是可以继续执行其他的任务呢 线程池是一种多线程处理形式处理过程中将任务添加到队列然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小以默认的优先级运行并处于多线程单元中。如果某个线程在托管代码中空闲如正在等待某个事件则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙但队列中包含挂起的工作则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队但他们要等到其他线程完成后才启动。 2线程池原理 在各个编程语言的语种中都有线程池的概念并且很多语言中直接提供了线程池作为程序猿直接使用就可以了下面介绍一下线程池的实现原理 线程池的组成主要分为3个部分这三部分配合工作就可以得到一个完整的线程池 1. 任务队列存储需要处理的任务由工作的线程来处理这些任务 通过线程池提供的API函数将一个待处理的任务添加到任务队列或者从任务队列中删除已处理的任务会被从任务队列中删除线程池的使用者也就是调用线程池函数往任务队列中添加任务的线程就是生产者线程 2. 工作的线程任务队列任务的消费者N个 线程池中维护了一定数量的工作线程他们的作用是是不停的读任务队列从里边取出任务并处理工作的线程相当于是任务队列的消费者角色如果任务队列为空工作的线程将会被阻塞使用条件变量/信号量阻塞如果阻塞之后有了新的任务由生产者将阻塞解除工作线程开始工作 3. 管理者线程不处理任务队列中的任务1个 它的任务是周期性的对任务队列中的任务数量以及处于忙状态的工作线程个数进行检测 当任务过多的时候可以适当的创建一些新的工作线程当任务过少的时候可以适当的销毁一些工作的线程 3线程池的使用QRunnable 在Qt中使用线程池需要先创建任务添加到线程池中的每一个任务都需要是一个QRunnable类型因此在程序中需要创建子类继承QRunnable这个类然后重写run()方法在这个函数中编写要在线程池中执行的任务并将这个子类对象传递给线程池这样任务就可以被线程池中的某个工作的线程处理掉了。 QRunnable类常用函数不多主要是设置任务对象传给线程池后是否需要自动析构。 [pure virtual] void QRunnable::run(); 在子类中必须要重写的函数, 里边是任务的处理流程 void QRunnable::setAutoDelete(bool autoDelete); 参数设置为 true: 这个任务对象在线程池中的线程中处理完毕, 这个任务对象就会自动销毁参数设置为 false: 这个任务对象在线程池中的线程中处理完毕, 对象需要手动销毁 bool QRunnable::autoDelete() const; 获取当前任务对象的析构方式,返回true-自动析构, 返回false-手动析构 创建一个要添加到线程池中的任务类处理方式如下 class MyWork : public QObject, public QRunnable {Q_OBJECT public:explicit MyWork(QObject *parent nullptr){// 任务执行完毕,该对象自动销毁setAutoDelete(true);}~MyWork();void run() override{}; }在上面的示例中MyWork类是一个多重继承如果需要在这个任务中使用Qt的信号槽机制进行数据的传递就必须继承Qobject这个类如果不使用信号槽传递数据就可以不继承了只继承QRunnable即可。 class MyWork :public QRunnable {Q_OBJECT public:explicit MyWork(){// 任务执行完毕,该对象自动销毁setAutoDelete(true);}~MyWork();void run() override{}; }4QThreadPool Qt中的QThreadPool类管理了一组QThreads,里边还维护了一个任务队列。QThreadPool管理和回收各个QThread对象以帮助减少使用线程的程序中的线程创建成本。每个Qt应用程序都有一个全局QThreadPool对象可以通过调用globalInstance()来访问它。也可以单独创建一个QThreadPool对象使用。 线程池常用的API函数如下 int maxThreadCount() const; void setMaxThreadCount(int maxThreadCount); 获取和设置线程中的最大线程个数 void QThreadPool::start(QRunnable * runnable, int priority 0); 给线程池添加任务, 任务是一个 QRunnable 类型的对象,如果线程池中没有空闲的线程了, 任务会放到任务队列中, 等待线程处理 bool QThreadPool::tryStart(QRunnable * runnable); 如果线程池中没有空闲的线程了, 直接返回值, 任务添加失败, 任务不会添加到任务队列中 int QThreadPool::activeThreadCount() const; 线程池中被激活的线程的个数(正在工作的线程个数) bool QThreadPool::tryTake(QRunnable *runnable); 尝试性的将某一个任务从线程池的任务队列中删除, 如果任务已经开始执行就无法删除了 void QThreadPool::clear(); 将线程池中的任务队列里边没有开始处理的所有任务删除, 如果已经开始处理了就无法通过该函数删除了 static QThreadPool * QThreadPool::globalInstance(); 在每个Qt应用程序中都有一个全局的线程池对象, 通过这个函数直接访问这个对象 一般情况下我们不需要在Qt程序中创建线程池对象直接使用Qt为每个应用程序提供的线程池全局对象即可。得到线程池对象之后调用start()方法就可以将一个任务添加到线程池中这个任务就可以被线程池内部的线程池处理掉了使用线程池比自己创建线程的这种多种多线程方式更加简单和易于维护。 使用示例 class MyWork :public QRunnable {Q_OBJECT public:explicit MyWork();~MyWork();void run() override; }MyWork::MyWork() : QRunnable() {// 任务执行完毕,该对象自动销毁setAutoDelete(true); } void MyWork::run() {// 业务处理代码...... } MyWork::MyWork() : QRunnable() {// 任务执行完毕,该对象自动销毁setAutoDelete(true); } void MyWork::run() {// 业务处理代码...... } 示例生成随机数然后使用冒泡排序和快速排序对其进行处理 这个示例再用线程池实现一次 mythread.h #ifndef MYTHREAD_H #define MYTHREAD_H#include QThread #includeQVector #includeQRunnable//生成随机数将构造类的名字直接改成Generate更明确一些 class Generate :public QObject, public QRunnable {Q_OBJECT public:explicit Generate(QObject *parent nullptr);//将主线程传递过来的数保存到m_numvoid recvNum(int num);void run() override;signals:void sendArray(QVectorint);private:int m_num;};class BubbleSort :public QObject, public QRunnable {Q_OBJECT public:explicit BubbleSort(QObject *parent nullptr);//将主线程传递过来的数保存到m_numvoid recvArray(QVectorint list);void run() override;signals:void finish(QVectorint);private:QVectorint m_list;};class QuickSort :public QObject, public QRunnable {Q_OBJECT public:explicit QuickSort(QObject *parent nullptr);//将主线程传递过来的数保存到m_numvoid recvArray(QVectorint list);void run() override;private:void quickSort(QVectorint list,int l, int r);signals:void finish(QVectorint);private:QVectorint m_list;};#endif // MYTHREAD_Hmythread.cpp #include mythread.h #includeQElapsedTimer #includeQDebug #includeQThreadGenerate::Generate(QObject *parent) :QObject(parent),QRunnable() {//设置自动析构setAutoDelete(true); }void Generate::recvNum(int num) {m_num num; }void Generate::run() {qDebug() 生成随机数的线程的线程地址 QThread::currentThread();QVectorint list;//计时QElapsedTimer time;time.start();for(int i0; im_num; i){list.push_back(qrand() % 100000);}int milsec time.elapsed();qDebug() 生成 m_num 随机数总用时 milsec 毫秒;//发送给主线程emit sendArray(list); }BubbleSort::BubbleSort(QObject *parent):QObject(parent),QRunnable() {//设置自动析构setAutoDelete(true); }void BubbleSort::recvArray(QVectorint list) {m_list list; }void BubbleSort::run() {qDebug() 冒泡排序的线程的线程地址 QThread::currentThread();//计时QElapsedTimer time;time.start();//冒泡排序int temp;for(int i0;im_list.size();i){for(int j0;jm_list.size()-i-1;j){if(m_list[j] m_list[j1]){temp m_list[j];m_list[j] m_list[j1];m_list[j1] temp;}}}int milsec time.elapsed();qDebug() 冒泡排序用时 milsec 毫秒;emit finish(m_list); }QuickSort::QuickSort(QObject *parent):QObject(parent),QRunnable() {//设置自动析构setAutoDelete(true); }void QuickSort::recvArray(QVectorint list) {m_list list; }void QuickSort::run() {qDebug() 快速排序的线程的线程地址 QThread::currentThread();//计时QElapsedTimer time;time.start();//快速排序quickSort(m_list,0,m_list.size()-1);int milsec time.elapsed();qDebug() 快速排序用时 milsec 毫秒;emit finish(m_list); }void QuickSort::quickSort(QVectorint s, int l, int r) {if(lr){int i l,j r;int x s[l];while(i j){while(i j s[j] x){j--;}if(i j){s[i] s[j];}while(i j s[i] x){i;}if(i j){s[j--] s[i];}}s[i] x;quickSort(s,l,i-1);quickSort(s,i1,r);} } mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include QMainWindowQT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent nullptr);~MainWindow();signals:void starting(int num);private:Ui::MainWindow *ui; }; #endif // MAINWINDOW_Hmainwindow.cpp #include mainwindow.h #include ui_mainwindow.h #includemythread.h #includeQThreadPool MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui-setupUi(this);//1.创建任务对象Generate* gen new Generate;BubbleSort* bubble new BubbleSort;QuickSort* quick new QuickSort;connect(this,MainWindow::starting,gen,Generate::recvNum);//2.启动子线程connect(ui-start,QPushButton::clicked,this,[](){emit starting(10000);QThreadPool::globalInstance()-start(gen);});//随机数子线程发送来的数据触发冒泡排序和快速排序接收数据connect(gen,Generate::sendArray,bubble,BubbleSort::recvArray);connect(gen,Generate::sendArray,quick,QuickSort::recvArray);connect(gen,Generate::sendArray,this,[](QVectorint list){//启动两个任务QThreadPool::globalInstance()-start(bubble);QThreadPool::globalInstance()-start(quick);for (int i0; ilist.size(); i) {ui-randlist-addItem(QString::number(list.at(i)));}});//两个排序处理数据connect(bubble,BubbleSort::finish,this,[](QVectorint list){for (int i0; ilist.size(); i) {ui-bubblelist-addItem(QString::number(list.at(i)));}});connect(quick,QuickSort::finish,this,[](QVectorint list){for (int i0; ilist.size(); i) {ui-quicklist-addItem(QString::number(list.at(i)));}}); }MainWindow::~MainWindow() {delete ui; } main.cpp  #include mainwindow.h#include QApplicationint main(int argc, char *argv[]) {QApplication a(argc, argv);qRegisterMetaTypeQVectorint(QVectorint);MainWindow w;w.show();return a.exec(); }④线程安全 实现线程互斥和同步常用的类有 互斥锁QMutex、QMutexLocker条件变量QWaitCondition信号量QSemaphore读写锁QReadLocker、QWriteLocker、QReadWriteLock 多个线程加锁的对象得是同一个对象不同对象此时不会产生锁的互斥也就无法把并发执行变为串行执行 1互斥锁 互斥锁是一种保护和防止多个线程同时访问同一对象实例的方法在Qt中互斥锁主要是通过QMutex类来处理。 OMutex 特点QMutex是Qt框架提供的互斥锁类用于保护共享资源的访问实现线程间的互斥操作。 用途在多线程环境下通过互斥锁来控制对共享数据的访问确保线程安全。 QMutex mutex;mutex.lock();//上锁 //访问共享资源 //…… mutex.unlock();//解锁 OMutexLocker 特点OMutexLocker是QMutex的辅助类使用RAII(Resource Acquisition Is Initialization)方式对互斥锁进行上锁和解锁操作。 用途简化对互斥锁的上锁和解锁操作避免忘记解锁导致的死锁等问题。 QMutex mutex; {QMutexLocker locker(mutex);//在作用域内自动上锁//访问共享资源//... }//在作用域结束时自动解锁QMutex mutex; 创建了一个 QMutex 对象。在大括号 {} 内创建了 QMutexLocker 的实例 locker它接受 mutex 的地址作为参数。这将锁定 mutex。在大括号内可以安全地访问共享资源因为互斥量已经被锁定防止了其他线程同时访问。当离开大括号的作用域时locker 的实例被销毁它的析构函数会自动调用 mutex.unlock()从而释放互斥量。 QReadWriteLockerQReadLockerQWriteLocker 特点 QReadWriteLock是读写锁类用于控制读和写的并发访问。QReadLocker用于读操作上锁允许多个线程同时读取共享资源。QWriteLocker用于写操作上锁只允许一个线程写入共享资源。 用途在某些情况下多个线程可以同时读取共享数据但只有一个线程能够进行写操作。读写锁提供了更高效的并发访问方式。 OReadWriteLock rwLock; //在读操作中使用读锁 {QReadLocker locker(rwLock);//在作用域内自动上读锁//读取共享资源//…… }//在作用域结束时自动解读锁//在写操作中使用写锁 {QWriteLocker locker(rwLock);//在作用域内自动上写锁//修改共享资源//…… }//在作用域结束时自动解写锁 2条件变量 在多线程编程中假设除了等待操作系统正在执行的线程之外某个线程还必须等待某些条件满足才能执行这时就会出现问题。这种情况下线程会很自然地使用锁的机制来阻塞其他线程因为这只是线程的轮流使用并且该线程等待某些特定条件人们会认为需要等待条件的线程在释放互斥锁或读写锁之后进入了睡眠状态这样其他线程就可以继续运行。当条件满足时等待条件的线程将被另一个线程唤醒。 在Qt中专门提供了QWaitCondition类来解决像上述这样的问题。 特点QWaitCondition是Qt框架提供的条件变量类用于线程之间的消息通信和同步。 用途在某个条件满足时等待或唤醒线程用于线程的同步和协调。 3信号量 有时在多线程编程中需要确保多个线程可以相应的访问一个数量有限的相同资源。例如运行程序的设备可能是非常有限的内存因此我们更希望需要大量内存的线程将这一事实考虑在内并根据可用的内存数量进行相关操作多线程编程中类似问题通常用信号量来处理。信号量类似于增强的互斥锁不仅能完成上锁和解锁操作而且可以跟踪可用资源的数量。 特点QSemaphore是Qt框架提供的计数信号量类用于控制同时访问共享资源的线程数量。 用途限制并发线程数量用于解决一些资源有限的问题。
http://www.dnsts.com.cn/news/196606.html

相关文章:

  • 南京制作手机网站包头教育平台网站建设
  • 网站建设百灵鸟优化可以看网站的浏览器有哪些
  • 华美天一建筑公司网站网站建设的科目
  • 小榄网站开发wordpress title插件
  • 交易类网站seo怎么做湖北seo优化诊断
  • 网站线上推广方式广告设计作品集
  • 湖北省建设厅官方网站微信导航网站如何建设
  • vs2010怎么做网站前台商洛网站建设哪家好
  • 珠海专业做网站制作单页设计风格
  • 申请号的网站品牌建设目标包括哪些方面
  • 建设一个公司网站需要什么知识宣传片影视拍摄公司
  • 网站建设策划ppt张店做网站公司
  • 鹤山做网站公司seo云优化方法
  • 深圳网站. 方维网络手机 网站内 搜索
  • 给网站底部做友情链接国内优秀门户网站设计
  • 在哪一个网站做社保申报做语音聊天网站要多少钱
  • 上海公司网站建设以子wordpress 加入js
  • 有什么好的书写网站腾讯云域名价格
  • 长春网站制作长春万网电子商务平台方案
  • ui设计培训资料合肥网站seo推广
  • 网站和网页的设计原则管理者应具备的能力
  • 大庆做网站找谁微信开发网站建设程序
  • 静态html网站打包成exe企业邮箱注册账号
  • 百度收录不了网站吗做标书的网站
  • 做网站的简称注册小规模公司需要什么资料
  • 生活服务网站开发深圳网警
  • 域名访问网站下前几年做哪个网站能致富
  • 网页设计做音乐网站4399电脑版网页链接
  • 北京建筑公司网站天津seo培训
  • 构建网站的步骤云南旅行社网站建设