zoukankan      html  css  js  c++  java
  • Qt中的QThread:使用QSemaphore进行多线程数据同步

    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,因为没有资源可用。

    运行结果如下图:

  • 相关阅读:
    SpringMVC的各种注解
    ThreadLocal的一些总结
    HashTable和HashMap
    SaxReader读取xml
    Java多线程(七):ReentrantLock
    Java多线程(六):wait(),notify()和notifyAll()
    Java多线程(五):死锁
    Java多线程(四):volatile
    Java多线程(三):synchronized
    每日一题,每日一字
  • 原文地址:https://www.cnblogs.com/weiweiqiao99/p/14344217.html
Copyright © 2011-2022 走看看