1 #ifndef THREADTEST1_H 2 #define THREADTEST1_H 3 4 #include <QObject> 5 #include <QThread> 6 #include <QDebug> 7 #include <QRandomGenerator> 8 #include <QWaitCondition> 9 #include <QMutex> 10 #include <QSemaphore> 11 12 class ThreadTest1 : public QThread 13 { 14 Q_OBJECT 15 public: 16 ThreadTest1(int _index, QWaitCondition *_condition, QMutex *_mutex, QSemaphore *_semaphore, QObject *parent = nullptr); 17 ~ThreadTest1(); 18 signals: 19 void updateProgress(int); 20 21 public: 22 void doSomething(); 23 24 void run() override; 25 26 QWaitCondition *condition; 27 QMutex *mutex; 28 QSemaphore *semaphore; 29 int index; 30 31 private: 32 int nProgress = 0; 33 QRandomGenerator *generator = QRandomGenerator::global(); 34 35 }; 36 37 #endif // THREADTEST1_H
1 #include "threadtest1.h" 2 3 ThreadTest1::ThreadTest1(int _index, QWaitCondition *_condition, QMutex *_mutex, QSemaphore *_semaphore, QObject *parent) 4 : QThread(parent) 5 , index(_index) 6 , condition(_condition) 7 , mutex(_mutex) 8 , semaphore(_semaphore) 9 { 10 qDebug() << __FUNCTION__ << " : " << index; 11 } 12 13 ThreadTest1::~ThreadTest1() 14 { 15 qDebug() << __FUNCTION__ << " : " << index; 16 } 17 18 void ThreadTest1::doSomething() 19 { 20 mutex->lock(); 21 qDebug() << index << " :enter wait block"; 22 semaphore->release(1); 23 condition->wait(mutex); 24 mutex->unlock(); 25 qDebug() << index << " :start "; 26 nProgress = 0; 27 for( ; ; ) 28 { 29 msleep(1000); 30 nProgress += generator->bounded(1, 20); 31 if(nProgress >= 100) 32 { 33 nProgress = 100; 34 emit updateProgress(nProgress); 35 break; 36 } 37 else{ 38 emit updateProgress(nProgress); 39 } 40 } 41 qDebug() << index << " : finished!"; 42 43 } 44 45 void ThreadTest1::run() 46 { 47 doSomething(); 48 }
1 #ifndef WIDGET_H 2 #define WIDGET_H 3 4 #include <QWidget> 5 #include "threadtest1.h" 6 #include <QProgressBar> 7 #include <QVBoxLayout> 8 #include <QVector> 9 #include <QPushButton> 10 #include <QWaitCondition> 11 #include <QMutex> 12 #include <QThread> 13 #include <QSemaphore> 14 15 QT_BEGIN_NAMESPACE 16 namespace Ui { class Widget; } 17 QT_END_NAMESPACE 18 19 class Widget : public QWidget 20 { 21 Q_OBJECT 22 23 public: 24 Widget(QWidget *parent = nullptr); 25 ~Widget(); 26 27 private slots: 28 void slotPushButton(); 29 30 public: 31 Ui::Widget *ui; 32 QWaitCondition condition; 33 QMutex mutex; 34 QSemaphore semaphore; 35 36 public: 37 QVector<ThreadTest1*> vecThread; 38 QVector<QProgressBar*> vecProgressBar; 39 QVBoxLayout* layout; 40 QPushButton *btn; 41 const int cnt = 10; 42 void init(); 43 void reset(); 44 45 46 }; 47 #endif // WIDGET_H
1 #include "widget.h" 2 #include "ui_widget.h" 3 4 struct ThreadClass : public QThread 5 { 6 Widget *widget; 7 void run() override 8 { 9 widget->reset(); 10 ThreadTest1 *thread; 11 for(int i = 0; i < widget->cnt; i++) 12 { 13 thread = new ThreadTest1(i, &widget->condition, &widget->mutex, &widget->semaphore); 14 widget->vecThread.push_back(thread); 15 connect(widget->vecThread.at(i), &ThreadTest1::updateProgress, widget->vecProgressBar.at(i), &QProgressBar::setValue); 16 connect(widget->vecThread.at(i), &ThreadTest1::finished, this, [=](){ 17 thread->deleteLater(); 18 widget->vecThread[i] = nullptr; 19 }); 20 widget->vecThread.at(i)->start(); 21 } 22 widget->semaphore.acquire(widget->cnt); 23 qDebug() << "all ready"; 24 widget->condition.wakeAll(); 25 } 26 27 ThreadClass(Widget *_widget) 28 : widget(_widget) 29 { 30 qDebug() << __FUNCTION__; 31 } 32 33 ~ThreadClass() 34 { 35 qDebug() << __FUNCTION__; 36 } 37 }; 38 39 Widget::Widget(QWidget *parent) 40 : QWidget(parent) 41 , ui(new Ui::Widget) 42 { 43 ui->setupUi(this); 44 init(); 45 } 46 47 Widget::~Widget() 48 { 49 delete ui; 50 } 51 52 void Widget::slotPushButton() 53 { 54 ThreadClass *thread = new ThreadClass(this); 55 connect(thread, &ThreadClass::finished, thread, &QObject::deleteLater); 56 thread->start(); 57 qDebug() << "Leave " << __FUNCTION__; 58 } 59 60 61 void Widget::init() 62 { 63 QProgressBar *bar; 64 layout = new QVBoxLayout(this); 65 for(int i = 0; i < cnt; i++) 66 { 67 bar = new QProgressBar(this); 68 bar->setRange(0, 100); 69 bar->reset(); 70 vecProgressBar.push_back(bar); 71 layout->addWidget(bar); 72 } 73 btn = new QPushButton("Start", this); 74 connect(btn, &QPushButton::clicked, this, &Widget::slotPushButton); 75 layout->addWidget(btn); 76 } 77 78 void Widget::reset() 79 { 80 for(int i = 0; i < cnt; i++) 81 { 82 vecProgressBar[i]->reset(); 83 } 84 vecThread.clear(); 85 }