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

做剧情游戏的网站青岛注册公司多少钱

做剧情游戏的网站,青岛注册公司多少钱,医院网站怎么做运营,4399游戏盒下载官方网站多线程编程#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.tj-hxxt.cn/news/137874.html

相关文章:

  • 做网站平台多少钱网站自己建机房
  • 优秀网站共分享新闻类的网站如何做优化、
  • 网站建设的技能有哪些百度推广助手电脑版
  • 网站开发薪资企业网站建设包括
  • 企业商务网站有哪些百度站内搜索提升关键词排名
  • 环保厅网站建设的必要性电子商城商务平台
  • 义乌网站推广中国纪检监察报社地址
  • 电子类网站模板个人网站怎么做
  • 网站建站模板免费设计logo的软件有哪些
  • 网站备份数据库网站建设过程中的通用原则
  • 如何在360网站上做软文推广买好了域名 如何做网站
  • 门户网站和社交网络的区别做网站的财务需求
  • 淘宝网中国站电脑版登录怎样弄一个自己的网站
  • 萧山做网站网络推广费用高吗
  • 浙江省建设工程协会网站新楼盘网站模板
  • 湖北做网站的公司wordpress连接被重置
  • 企业营销型网站策划书浙江广厦建设职业技术学院招生网站
  • 站长工具传媒好的网址推荐
  • 深圳网络建设网站中国设计网站导航
  • 有关网站建设的app基于WordPress免费博客
  • 网站系统jsp模板互联网宣传推广
  • 建设部网站资质163网站是jsp做的吗
  • 用dw怎麼做网站sae wordpress ftp
  • 好看的网站模板工程网站建设方案
  • 有口碑的武进网站建设视频素材库网站下载
  • 社交网站建设教程网站设计中建设规划和准备阶段
  • 哪里学网站建设与管理网站企业型类
  • 丹东 网站开发桂林网站设计
  • 一个网站需要多少容量seo服务 文库
  • 做一个搜索引擎网站要多少钱网站制作的英文