20210127:在生产者、消费者的方法中添加线程挂起方法QThread::usleep(10),使ui不卡。
20210128:在添加Track类(保存生产者Producer生成的每组数据),在ui界面中使用model-view同步显示生产者生成的数据,model-view不会对主线程造成卡顿。对消费者同样创建view,还没有进行model绑定。
避免引起主线程的阻塞,Qt在子线程中处理大数据,当多个子线程需要处理同一块数据时,需要使用数据同步,避免出现调用错乱情况,在这里我们在两个子线程使用QSemaphore作为标志位,对数组进行标识,生产者线程将生成的资源存入数组,消费者数组消耗数组内的资源,当有一方的速度过快导致数组资源耗尽时,该子线程被阻塞,直到有资源时子线程继续。代码如下:
在全局变量中声明数组、数组大小、资源总量:
constant_variable.h
1 #ifndef CONSTANT_VARIABLE_H 2 #define CONSTANT_VARIABLE_H 3 4 // 所有变量在h文件中均是声明,定义在cpp文件中 5 6 /***************************************************************************************** 7 @copyright 2013-2020 8 @author qiaowei 9 @contact weiweiqiao@126.com 10 @version 1.0 11 @date 2021-01-24 12 @brief h文件声明extern变量,cpp文件定义变量 13 ******************************************************************************************/ 14 15 #include <QSemaphore> 16 17 /*************************************************************************** 18 @copyright 2013-2020 19 @author qiaowei 20 @contact weiweiqiao@126.com 21 @version 1.0 22 @date 2021-01-24 23 @brief 设置循环保存数据的数组大小,相当于设置“缓存”大小 24 ***************************************************************************/ 25 extern const int BUFFER_SIZE; 26 27 /*************************************************************************** 28 @copyright 2013-2020 29 @author qiaowei 30 @contact weiweiqiao@126.com 31 @date 2021-01-24 32 @brief 要读取的总资源数量,数据量大,无法一次读取完,需要长时间,分批读取 33 ***************************************************************************/ 34 extern const int DATA_SIZE; 35 36 /*************************************************************************** 37 @copyright 2013-2020 38 @author qiaowei 39 @contact weiweiqiao@126.com 40 @date 2021-01-24 41 @brief 循环使用,保存数据资源的数组 42 ***************************************************************************/ 43 extern char BUFFER[]; 44 45 /*************************************************************************** 46 @copyright 2013-2020 47 @author qiaowei 48 @contact weiweiqiao@126.com 49 @date 2021-01-24 50 @brief 标识Producer可以保存资源的空余位置的数量,保存在数组中的数据量,因为初 51 始状态数组中没有任何数据,数组有DATA_SIZE个资源可用 52 ***************************************************************************/ 53 extern QSemaphore PRODUCER_SPACE; 54 55 /*************************************************************************** 56 @copyright 2013-2020 57 @author qiaowei 58 @contact weiweiqiao@126.com 59 @date 2021-01-24 60 @brief 标识Consumer可以使用的已保存资源的数量,因为初始时没有数据可供Consumer 61 使用,初始资源有0个 62 ***************************************************************************/ 63 extern QSemaphore CONSUMER_SPACE; 64 65 #endif // CONSTANT_VARIABLE_H
constant_variable.cpp
1 #include "constant_variable.h" 2 3 const int BUFFER_SIZE(4096); 4 5 const int DATA_SIZE(100000); 6 7 // 定义数组大小为BUFFER_SIZE 8 char BUFFER[BUFFER_SIZE]; 9 10 // 初始时可用资源位BUFFER_SIZE 11 QSemaphore PRODUCER_SPACE(BUFFER_SIZE); 12 13 QSemaphore CONSUMER_SPACE(0);
创建窗体:
Producer按钮生成资源,保存到数组中,在左侧文本框中显示Producer所在的线程及生成的资源。Consumer按钮消耗数组中的资源,在左侧文本框中显示Consumer所在的线程及消耗的资源。这两个按钮是单独运行。Both_start_PushButton按钮同时启动两个子线程,一个生产资源,一个消耗资源,生产和消耗的都在左边的文本框中显示。
窗口代码如下:
producer_consumer_dialog.ui 代码:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <ui version="4.0"> 3 <class>Producer_consumer_dialog</class> 4 <widget class="QDialog" name="Producer_consumer_dialog"> 5 <property name="geometry"> 6 <rect> 7 <x>0</x> 8 <y>0</y> 9 <width>722</width> 10 <height>451</height> 11 </rect> 12 </property> 13 <property name="windowTitle"> 14 <string>Dialog</string> 15 </property> 16 <layout class="QVBoxLayout" name="verticalLayout_3"> 17 <item> 18 <layout class="QHBoxLayout" name="horizontalLayout"> 19 <item> 20 <widget class="QPlainTextEdit" name="producer_plainTextEdit"/> 21 </item> 22 <item> 23 <layout class="QVBoxLayout" name="verticalLayout"> 24 <item> 25 <widget class="QPushButton" name="producer_pushButton"> 26 <property name="text"> 27 <string>Producer</string> 28 </property> 29 </widget> 30 </item> 31 <item> 32 <spacer name="verticalSpacer"> 33 <property name="orientation"> 34 <enum>Qt::Vertical</enum> 35 </property> 36 <property name="sizeType"> 37 <enum>QSizePolicy::Expanding</enum> 38 </property> 39 <property name="sizeHint" stdset="0"> 40 <size> 41 <width>20</width> 42 <height>40</height> 43 </size> 44 </property> 45 </spacer> 46 </item> 47 </layout> 48 </item> 49 <item> 50 <widget class="QTableView" name="producer_tableView"/> 51 </item> 52 </layout> 53 </item> 54 <item> 55 <layout class="QHBoxLayout" name="horizontalLayout_2"> 56 <item> 57 <widget class="QPlainTextEdit" name="consumer_plainTextEdit"/> 58 </item> 59 <item> 60 <layout class="QVBoxLayout" name="verticalLayout_2"> 61 <item> 62 <widget class="QPushButton" name="consumer_pushButton"> 63 <property name="text"> 64 <string>Consumer</string> 65 </property> 66 </widget> 67 </item> 68 <item> 69 <spacer name="verticalSpacer_2"> 70 <property name="orientation"> 71 <enum>Qt::Vertical</enum> 72 </property> 73 <property name="sizeHint" stdset="0"> 74 <size> 75 <width>20</width> 76 <height>40</height> 77 </size> 78 </property> 79 </spacer> 80 </item> 81 </layout> 82 </item> 83 <item> 84 <widget class="QTableView" name="consumer_tableView"/> 85 </item> 86 </layout> 87 </item> 88 <item> 89 <layout class="QHBoxLayout" name="horizontalLayout_3"> 90 <item> 91 <spacer name="horizontalSpacer"> 92 <property name="orientation"> 93 <enum>Qt::Horizontal</enum> 94 </property> 95 <property name="sizeHint" stdset="0"> 96 <size> 97 <width>348</width> 98 <height>20</height> 99 </size> 100 </property> 101 </spacer> 102 </item> 103 <item> 104 <widget class="QPushButton" name="both_start_pushButton"> 105 <property name="text"> 106 <string>Both_start_PushButton</string> 107 </property> 108 </widget> 109 </item> 110 </layout> 111 </item> 112 </layout> 113 </widget> 114 <resources/> 115 <connections/> 116 </ui>
producer_consumer_dialog.h 文件:
1 #ifndef PRODUCER_CONSUMER_DIALOG_H 2 #define PRODUCER_CONSUMER_DIALOG_H 3 4 #include <QDialog> 5 #include <QThread> 6 7 QT_BEGIN_NAMESPACE 8 class Producer_move_to_thread; 9 class Consumer_move_to_thread; 10 class Producer_table_model; 11 //class QCloseEvent; 12 QT_END_NAMESPACE 13 14 namespace Ui { 15 class Producer_consumer_dialog; 16 } 17 18 /***************************************************************************************** 19 @copyright 2013-2020 20 @author qiaowei 21 @contact weiweiqiao@126.com 22 @version 1.0 23 @date 2021-01-27 24 @brief 创建主窗口,生成创造者producer,并在子线程-1生产资源。生成消费者consumer,并在子线程-2消耗生 25 产资源。资源均存储在BUFFER[]中 26 ******************************************************************************************/ 27 class Producer_consumer_dialog : public QDialog 28 { 29 Q_OBJECT 30 31 public: 32 explicit Producer_consumer_dialog(QWidget *parent = nullptr); 33 ~Producer_consumer_dialog(); 34 35 protected: 36 virtual void closeEvent(QCloseEvent* ev); 37 38 private: 39 /*************************************************************************** 40 @author qiaowei 41 @contact weiweiqiao@126.com 42 @version 1.0 43 @date 2021-01-27 44 @brief 初始化窗体控件 45 ***************************************************************************/ 46 void init_widgets(); 47 48 /*************************************************************************** 49 @author qiaowei 50 @contact weiweiqiao@126.com 51 @version 1.0 52 @date 2021-01-27 53 @brief 初始化私有变量,将producer_,consumer_放入各自的子线程 54 ***************************************************************************/ 55 void init_instances(); 56 57 /*************************************************************************** 58 @author qiaowei 59 @contact weiweiqiao@126.com 60 @version 1.0 61 @date 2021-01-27 62 @brief 实例化信号槽 63 ***************************************************************************/ 64 void init_connections(); 65 66 private slots: 67 /*************************************************************************** 68 @author qiaowei 69 @contact weiweiqiao@126.com 70 @version 1.0 71 @date 2021-01-27 72 @brief 将字符串content设置到文本框producer_plainTextEdit 73 @param content 字符串 74 ***************************************************************************/ 75 void set_producer_plain_text(quint32 serial_number, quint64 thread_id, char ch); 76 77 /*************************************************************************** 78 @author qiaowei 79 @contact weiweiqiao@126.com 80 @version 1.0 81 @date 2021-01-27 82 @brief 将字符串content设置到文本框consumer_plainTextEdit 83 @param content 字符串 84 ***************************************************************************/ 85 void set_consumer_plain_text(QString content); 86 87 private: 88 Ui::Producer_consumer_dialog *ui; 89 90 Producer_move_to_thread* producer_; 91 Consumer_move_to_thread* consumer_; 92 93 QThread producer_thread_; 94 QThread consumer_thread_; 95 96 /*************************************************************************** 97 @author qiaowei 98 @contact weiweiqiao@126.com 99 @version 1.0 100 @date 2021-01-28 101 @brief 消费者产生数据对应的模型 102 ***************************************************************************/ 103 Producer_table_model* producer_table_model_; 104 }; 105 106 #endif // PRODUCER_CONSUMER_DIALOG_H
producer_consumer_dialog.cpp文件:
1 #include "producer_consumer_dialog.h" 2 #include "ui_producer_consumer_dialog.h" 3 4 #include "producer_move_to_thread.h" 5 #include "consumer_move_to_thread.h" 6 #include "producer_table_model.h" 7 8 Producer_consumer_dialog::Producer_consumer_dialog(QWidget *parent) : 9 QDialog(parent), 10 ui(new Ui::Producer_consumer_dialog) 11 { 12 ui->setupUi(this); 13 14 init_widgets(); 15 init_instances(); 16 init_connections(); 17 } 18 19 Producer_consumer_dialog::~Producer_consumer_dialog() 20 { 21 delete producer_; 22 delete consumer_; 23 delete producer_table_model_; 24 25 delete ui; 26 } 27 28 void Producer_consumer_dialog::closeEvent(QCloseEvent *ev) 29 { 30 // QThread::sleep(3); 31 if ( producer_thread_.isRunning()) { 32 producer_thread_.quit(); 33 producer_thread_.wait(); 34 } 35 36 if ( consumer_thread_.isRunning()) { 37 consumer_thread_.quit(); 38 consumer_thread_.wait(); 39 } 40 41 QDialog::closeEvent(ev); 42 } 43 44 void Producer_consumer_dialog::init_widgets() 45 { 46 // setFixedSize(sizeHint()); 47 resize(sizeHint()); 48 } 49 50 void Producer_consumer_dialog::init_instances() 51 { 52 producer_ = new Producer_move_to_thread(); 53 producer_->moveToThread(&producer_thread_); 54 producer_thread_.start(); 55 56 consumer_ = new Consumer_move_to_thread(); 57 consumer_->moveToThread(&consumer_thread_); 58 consumer_thread_.start(); 59 60 producer_table_model_ = new Producer_table_model(); 61 ui->producer_tableView->setModel(producer_table_model_); 62 } 63 64 void Producer_consumer_dialog::init_connections() 65 { 66 connect(ui->producer_pushButton, 67 &QPushButton::clicked, 68 producer_, 69 &Producer_move_to_thread::create_char_in_thread); 70 71 connect(ui->consumer_pushButton, 72 &QPushButton::clicked, 73 consumer_, 74 &Consumer_move_to_thread::create_char_in_thread); 75 76 connect(ui->both_start_pushButton, 77 &QPushButton::clicked, 78 ui->producer_pushButton, 79 &QPushButton::clicked); 80 81 connect(ui->both_start_pushButton, 82 &QPushButton::clicked, 83 ui->consumer_pushButton, 84 &QPushButton::clicked); 85 86 // 获取producer_生成的字符串 87 connect(producer_, 88 &Producer_move_to_thread::signal_index_id_content, 89 this, 90 &Producer_consumer_dialog::set_producer_plain_text); 91 92 connect(producer_, 93 &Producer_move_to_thread::signal_index_id_content, 94 producer_table_model_, 95 &Producer_table_model::add_data_to_track_list); 96 97 // 获取consumer_取得的字符串 98 connect(consumer_, 99 &Consumer_move_to_thread::signal_string, 100 this, 101 &Producer_consumer_dialog::set_consumer_plain_text); 102 } 103 104 void Producer_consumer_dialog::set_producer_plain_text(quint32 serial_number, quint64 thread_id, char ch) 105 { 106 QString content = 107 QString("%1: Producer thread id: %2, char: %3"). 108 arg(serial_number). 109 arg(thread_id). 110 arg(ch); 111 ui->producer_plainTextEdit->appendPlainText(content); 112 // ui->producer_plainTextEdit->setPlainText(content); 113 } 114 115 void Producer_consumer_dialog::set_consumer_plain_text(QString content) 116 { 117 ui->consumer_plainTextEdit->appendPlainText(content); 118 // ui->consumer_plainTextEdit->setPlaceholderText(content); 119 }
生产类
producer_move_to_thread.h 文件:
1 #ifndef PRODUCER_MOVE_TO_THREAD_H 2 #define PRODUCER_MOVE_TO_THREAD_H 3 4 #include <QObject> 5 6 /***************************************************************************************** 7 @copyright 2013-2020 8 @author qiaowei 9 @contact weiweiqiao@126.com 10 @version 1.0 11 @date 2021-01-28 12 @brief 生产者,会被移动到子线程中产生资源 13 ******************************************************************************************/ 14 class Producer_move_to_thread : public QObject 15 { 16 Q_OBJECT 17 18 public: 19 explicit Producer_move_to_thread(QObject *parent = nullptr); 20 ~Producer_move_to_thread(); 21 22 signals: 23 // void signal_string(quint32 serial_number, quint64 thread_id, char ch); 24 25 void signal_index_id_content(quint32 index, int id, char ch); 26 27 public slots: 28 void create_char_in_thread(); 29 }; 30 31 #endif // PRODUCER_MOVE_TO_THREAD_H
producer_move_to_thread.CPP 文件:
1 #include <QtDebug> 2 #include <QThread> 3 #include <QtGlobal> 4 #include "producer_move_to_thread.h" 5 #include "constant_variable.h" 6 7 Producer_move_to_thread::Producer_move_to_thread(QObject* parent): 8 QObject(parent) 9 { 10 11 } 12 13 Producer_move_to_thread::~Producer_move_to_thread() 14 { 15 16 } 17 18 void Producer_move_to_thread::create_char_in_thread() 19 { 20 for (int index(0); DATA_SIZE != index; ++index) { 21 // 生产1个资源(总共要产生的DATA_SZIE个资源),然后保存到BUFFER数组,BUFFER数组空余位置少1个 22 PRODUCER_SPACE.acquire(1); 23 24 // 计算获取资源序号、线程号、数据资源 25 quint32 serial_number = (quint32) (index + 1); 26 quint64 thread_id = (quint64) QThread::currentThreadId(); 27 char ch = "ABCDXYZ"[uint(std::rand()) % 7]; 28 BUFFER[index % BUFFER_SIZE] = ch; 29 30 qDebug()<< "Produce thread id: " << thread_id 31 << ", char: " << ch; 32 33 // 将数据传给窗体Producer_consumer_dialog 34 // emit signal_string(serial_number, thread_id, ch); 35 36 emit signal_index_id_content(serial_number, thread_id, ch); 37 38 // 线程挂起,不对主线程造成卡顿 39 QThread::usleep(10); 40 41 // 数组中已保存1个字符,Consumer获取1个可用资源 42 CONSUMER_SPACE.release(1); 43 } 44 }
资源消耗类
consumer_move_to_thread.h 文件:
1 #ifndef CONSUMER_MOVE_TO_THREAD_H 2 #define CONSUMER_MOVE_TO_THREAD_H 3 4 #include <QObject> 5 6 class Consumer_move_to_thread : public QObject 7 { 8 Q_OBJECT 9 public: 10 explicit Consumer_move_to_thread(QObject *parent = nullptr); 11 12 signals: 13 void signal_string(QString content); 14 15 public slots: 16 void create_char_in_thread(); 17 }; 18 19 #endif // CONSUMER_MOVE_TO_THREAD_H
consumer_move_to_thread.CPP 文件:
1 #include <QtDebug> 2 #include <QThread> 3 #include "consumer_move_to_thread.h" 4 #include "constant_variable.h" 5 6 Consumer_move_to_thread::Consumer_move_to_thread(QObject *parent) : 7 QObject(parent) 8 { 9 10 } 11 12 void Consumer_move_to_thread::create_char_in_thread() 13 { 14 for (int index(0); DATA_SIZE != index; ++index) { 15 // 消耗1个资源(总共要消耗DATA_SZIE个资源),从BUFFER数组中取出,BUFFER数组空余位置多1个。当 16 // 没有资源提供时,进程被挂起,待有足够资源后再执行后续程序 17 CONSUMER_SPACE.acquire(1); 18 19 qDebug()<< "Consumer thread id: " << (quint64) QThread::currentThreadId() 20 << ", char: " << (char) BUFFER[index % BUFFER_SIZE]; 21 22 QString content = 23 QString("%1: Consumer thread id: %2, char: %3"). 24 arg(index + 1). 25 arg((quint64) QThread::currentThreadId()). 26 arg(BUFFER[index % BUFFER_SIZE]); 27 28 emit signal_string(content); 29 //线程挂起,不对主线程造成卡顿 30 QThread::usleep(10); 31 32 // 使用数组中1个资源,数组释放1个空间,给生产者提供1个空余位置 33 PRODUCER_SPACE.release(1); 34 } 35 }
保存生产者生成的数据Track类:
Track.h
1 #ifndef TRACK_H 2 #define TRACK_H 3 4 #include <QtGlobal> 5 6 /***************************************************************************************** 7 @copyright 2013-2020 8 @author qiaowei 9 @contact weiweiqiao@126.com 10 @version 1.0 11 @date 2021-01-28 12 @brief 数据类,保存随机生成的资源 13 ******************************************************************************************/ 14 class Track 15 { 16 public: 17 /*************************************************************************** 18 @author qiaowei 19 @contact weiweiqiao@126.com 20 @version 1.0 21 @date 2021-01-28 22 @brief 构造函数 23 @param index 数据的生成序列号 24 @param thread_id 生成数据的线程号 25 @param ch 生成的资源数据 26 ***************************************************************************/ 27 explicit Track(quint32 index = 0, quint64 thread_id = 0, char ch = 'A'); 28 ~Track(); 29 30 /*************************************************************************** 31 @author qiaowei 32 @contact weiweiqiao@126.com 33 @version 1.0 34 @date 2021-01-28 35 @brief 拷贝构造函数 36 ***************************************************************************/ 37 Track(const Track& r_value); 38 39 /*************************************************************************** 40 @author qiaowei 41 @contact weiweiqiao@126.com 42 @version 1.0 43 @date 2021-01-28 44 @brief 赋值操作符 45 ***************************************************************************/ 46 Track& operator = (const Track& r_value); 47 48 quint32 get_index() const; 49 50 quint64 get_thread_id() const; 51 52 char get_char() const; 53 54 private: 55 quint32 index_; 56 quint64 thread_id_; 57 char char_; 58 }; 59 60 #endif // TRACK_H
Track.CPP
1 #include "track.h" 2 3 4 Track::Track(quint32 index, quint64 thread_id, char ch): 5 index_(index), 6 thread_id_(thread_id), 7 char_(ch) 8 { 9 10 } 11 12 Track::~Track() 13 { 14 15 } 16 17 Track::Track(const Track &r_value) 18 { 19 index_ = r_value.index_; 20 thread_id_ = r_value.thread_id_; 21 char_ = r_value.char_; 22 } 23 24 Track &Track::operator =(const Track &r_value) 25 { 26 if (this != &r_value) { 27 index_ = r_value.index_; 28 thread_id_ = r_value.thread_id_; 29 char_ = r_value.char_; 30 } 31 32 return *this; 33 } 34 35 quint32 Track::get_index() const 36 { 37 return index_; 38 } 39 40 quint64 Track::get_thread_id() const 41 { 42 return thread_id_; 43 } 44 45 char Track::get_char() const 46 { 47 return char_; 48 }
生产者模型Produer_table_model类:
Produer_table_model.h
1 #ifndef PRODUCER_TABLE_MODEL_H 2 #define PRODUCER_TABLE_MODEL_H 3 4 #include <QAbstractTableModel> 5 #include <QObject> 6 #include "track.h" 7 8 /***************************************************************************************** 9 @copyright 2013-2020 10 @author qiaowei 11 @contact weiweiqiao@126.com 12 @version 1.0 13 @date 2021-01-28 14 @brief 15 ******************************************************************************************/ 16 class Producer_table_model : public QAbstractTableModel 17 { 18 Q_OBJECT 19 20 public: 21 explicit Producer_table_model(QObject* parent = nullptr); 22 ~Producer_table_model(); 23 24 void add_data_to_track_list(quint32 serial_number, quint64 thread_id, char ch); 25 26 QList<Track>* get_track_list(); 27 28 protected: 29 virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; 30 31 virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; 32 33 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 34 35 virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 36 37 private: 38 QList<Track>* track_list_; 39 }; 40 41 #endif // PRODUCER_TABLE_MODEL_H
Produer_table_model.CPP
1 #include "producer_table_model.h" 2 3 Producer_table_model::Producer_table_model(QObject* parent): 4 QAbstractTableModel(parent), 5 track_list_(new QList<Track>()) 6 { 7 8 } 9 10 Producer_table_model::~Producer_table_model() 11 { 12 delete track_list_; 13 } 14 15 void Producer_table_model::add_data_to_track_list(quint32 serial_number, quint64 thread_id, char ch) 16 { 17 track_list_->append(Track(serial_number, thread_id, ch)); 18 19 QModelIndex header_model_index = createIndex(serial_number - 1, 0); 20 QModelIndex tail_model_index = createIndex(serial_number - 1, 2); 21 22 layoutChanged(); 23 } 24 25 QList<Track> *Producer_table_model::get_track_list() 26 { 27 return track_list_; 28 } 29 30 int Producer_table_model::rowCount(const QModelIndex &parent) const 31 { 32 Q_UNUSED(parent) 33 34 if ( track_list_) { 35 return track_list_->count(); 36 } else { 37 return 0; 38 } 39 } 40 41 int Producer_table_model::columnCount(const QModelIndex &parent) const 42 { 43 Q_UNUSED(parent) 44 45 // // 序号、线程号、数据资源 46 // return 3; 47 48 // 线程号、数据资源 49 return 2; 50 } 51 52 QVariant Producer_table_model::data(const QModelIndex &index, int role) const 53 { 54 if ( !index.isValid()) { 55 return QVariant(); 56 } 57 58 QVariant v; 59 if (Qt::DisplayRole == role) { 60 switch (index.column()) { 61 case 0: 62 v = track_list_->at(index.row()).get_thread_id(); 63 break; 64 65 case 1: 66 v = (QChar) track_list_->at(index.row()).get_char(); 67 break; 68 } 69 70 return v; 71 } 72 73 74 75 return QVariant(); 76 } 77 78 QVariant Producer_table_model::headerData(int section, Qt::Orientation orientation, int role) const 79 { 80 if ((Qt::DisplayRole == role) && 81 (Qt::Horizontal == orientation)) { 82 83 QString header_content; 84 switch (section) { 85 case 0: 86 header_content = tr("线程号"); 87 break; 88 89 case 1: 90 header_content = tr("数据"); 91 break; 92 } 93 94 return header_content; 95 } 96 97 return QAbstractTableModel::headerData(section, orientation, role); 98 }
在这里特别注意PRODUCER_SPACE和CONSUMER_SPACE的初始值,因为资源BUFFER数组初始资源为0,所以生产者Producer可用的数组空间为所有,消耗着Consumer可用的数组空间为0,因为没有资源可用。
运行结果如下图: