知識點:啟動進程 ,線程 ,線程同步互斥
1 啟動進程
應用場景:通常在qt中打開另一個程序
process模板
QString program = “/bin/ls";
QStringList arguments;
arguments << "-l" << “-a";QProcess *myProcess = new QProcess(parent);
myProcess->execute(program, arguments);
示例:
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QFileDialog>
#include <QProcess>
#include <QStringList>class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = 0);~Widget();
public slots:void showfile(){QString filename = QFileDialog::getOpenFileName();le->setText(filename);QStringList arg = {filename};QProcess ppp;ppp.execute("notepad", arg);}private:QLineEdit *le;QPushButton *pb;
};#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QVBoxLayout>Widget::Widget(QWidget *parent): QWidget(parent)
{le = new QLineEdit;pb = new QPushButton("showtxt");QVBoxLayout *vbox = new QVBoxLayout;vbox->addWidget(le);vbox->addWidget(pb);setLayout(vbox);connect(pb, SIGNAL(clicked(bool)), this, SLOT(showfile()));
}Widget::~Widget()
{}
效果在qt中使用文本編輯器打開一個文本。?
2 線程
應用場景:啟動一個線程和進程來輔助程序
線程:
class WorkerThread : public Qthread{
Q_OBJECTvoid run() {/* ... here is the expensive or blocking operation ... */emit resultReady(result);}
signals:void resultReady(const QString &s);};
WorkerThread x;
x.start();
-
void run()
方法:這是QThread
的一個虛函數,你需要在子類中重寫它以實現線程的任務。當調用線程的start()
方法時,這里的代碼將在新的線程中執行。 -
void resultReady(const QString &s)
信號:這是一個自定義信號,當線程完成工作并有結果可供返回時,將通過emit
關鍵字發射這個信號。 -
QT是信號驅動、或者異步驅動的框架,平時app需要執行到a.exec()才會執行
?
雙線程示例:一個線程打印數組,一個線程排序數組
thread_show.h(繼承QThread類)
#ifndef THREAD_SHOW_H
#define THREAD_SHOW_H#include <Qthread>
#include <QDebug>
#include <QMutex>class thread_show : public QThread
{Q_OBJECT
public:thread_show(char *p):m_arr(p){}void run() //這是QThread的一個虛函數(qt中斜線表示),你需要在子類中重寫它以實現線程的任務。當調用線程的start()方法時,這里的代碼將在新的線程中執行。{while(1){//lockqDebug()<<m_arr;sleep(1);}}
private:char *m_arr;};#endif // THREAD_SHOW_H
thread_show.cpp(重寫構造函數)
#include "thread_show.h"/*
thread_show::thread_show()
{}
*/
thread_rev.h
#ifndef THREAD_REV_H
#define THREAD_REV_H#include <QThread>class thread_rev : public QThread
{Q_OBJECT
public:thread_rev(char *p):m_arr(p){} //構造時,直接賦值效率高void run(){while(1){for(int i=0; i<5; i++){m_arr[i] ^= m_arr[9-i];m_arr[9-i] ^= m_arr[i];m_arr[i] ^= m_arr[9-i];}}}
private:char *m_arr;
};#endif // THREAD_REV_H
thread_rev.cpp(重寫構造函數)
#include "thread_rev.h"/*
thread_rev::thread_rev()
{}
*/
main.cpp
#include "widget.h"
#include <QApplication>
#include "thread_rev.h"
#include "thread_show.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);char arr[] = "0123456789";thread_show t1(arr); //打印thread_rev t2(arr); //翻轉數組t1.start();t2.start();return a.exec();
}
?效果:兩個線程同時操作,打印出來的數組無規律
?
3 線程互斥
官方示例
QSemaphore :QSemaphore sem(5); // sem.available() == 5sem.acquire(3); // sem.available() == 2sem.acquire(2); // sem.available() == 0sem.release(5); // sem.available() == 5sem.release(5); // sem.available() == 10sem.tryAcquire(1); // sem.available() == 9, returns truesem.tryAcquire(250); // sem.available() == 9, returns falseQMutex ://lockerQMutex mutex;void method1(){mutex.lock();mutex.unlock();}void method2(){mutex.lock();mutex.unlock();}
實驗示例:
thread_show.h
#ifndef THREAD_SHOW_H
#define THREAD_SHOW_H#include <Qthread>
#include <QDebug>
#include <QMutex>class thread_show : public QThread
{Q_OBJECT
public:thread_show(char *p, QMutex *l):m_arr(p), m_arrlock(l){}void run() //這是QThread的一個虛函數(qt中斜線表示),你需要在子類中重寫它以實現線程的任務。當調用線程的start()方法時,這里的代碼將在新的線程中執行。{while(1){m_arrlock->lock();qDebug()<<m_arr;m_arrlock->unlock();sleep(1);}}
private:char *m_arr;QMutex *m_arrlock;};#endif // THREAD_SHOW_H
thread_show.cpp
#include "thread_show.h"/*
thread_show::thread_show()
{}
*/
thread_rev.h
#ifndef THREAD_REV_H
#define THREAD_REV_H#include <QThread>
#include <QMutex>class thread_rev : public QThread
{Q_OBJECT
public:thread_rev(char *p, QMutex *l):m_arr(p), m_arrlock(l){}void run(){while(1){m_arrlock->lock();for(int i=0; i<5; i++){m_arr[i] ^= m_arr[9-i];m_arr[9-i] ^= m_arr[i];m_arr[i] ^= m_arr[9-i];}m_arrlock->unlock();}}
private:char *m_arr;QMutex *m_arrlock;};#endif // THREAD_REV_H
thread_rev.cpp
#include "thread_rev.h"/*
thread_rev::thread_rev()
{}
*/
main.cpp
#include "widget.h"
#include <QApplication>
#include "thread_rev.h"
#include "thread_show.h"
#include <QMutex>int main(int argc, char *argv[])
{QApplication a(argc, argv);char arr[] = "0123456789";QMutex arr_lock;thread_show t1(arr,&arr_lock); //打印thread_rev t2(arr,&arr_lock); //翻轉數組t1.start();t2.start();return a.exec();
}
??效果:兩個線程同時操作,打印出來的數組均為排序后的結果,排序中不會受到干擾
4 線程同步
目的:實現一個線程獲取資源需要等另一個線程釋放資源。
thread_hello.h
#ifndef THREAD_HELLO_H
#define THREAD_HELLO_H#include <QSemaphore>
#include <QThread>
#include <QDebug>class thread_hello : public QThread
{Q_OBJECT
public:thread_hello(QSemaphore *s):sem(s){ }void run(){while(1){qDebug()<<"hello";sleep(1);//Vsem->release();}}
private:QSemaphore *sem;
};#endif // THREAD_HELLO_H
thread_hello.cpp
#include "thread_hello.h"/*
thread_hello::thread_hello()
{}
*/
thread_world.h
#ifndef THREAD_WORLD_H
#define THREAD_WORLD_H#include <QThread>
#include <QDebug>
#include <QSemaphore>class thread_world : public QThread
{Q_OBJECT
public:thread_world(QSemaphore *s):sem(s){ }void run() //字體歪的就是虛函數{while(1){//Psem->acquire();qDebug()<<"world";}}
private:QSemaphore *sem;
};#endif // THREAD_WORLD_H
thread_world.cpp
#include "thread_hello.h"/*
thread_hello::thread_hello()
{}
*/
main.cpp
#include <QCoreApplication>
#include "thread_hello.h"
#include "thread_world.h"
#include <QSemaphore>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QSemaphore sem;thread_hello hello(&sem);thread_world world(&sem);hello.start();world.start();return a.exec();
}
效果,hello先打印,才會有world。?
?
綜合示例:實現兩個進度條在下載
mythread1.h
#ifndef MYTHREAD1_H
#define MYTHREAD1_H#include <QThread>class myThread1 : public QThread
{Q_OBJECT
signals:downloaded(int);
public:myThread1();void run(){for(int i=0;i<100; i++){//p1->setValue(i);emit downloaded(i);QThread::sleep(2);}}
};#endif // MYTHREAD1_H
mythread1.cpp
#include "mythread1.h"myThread1::myThread1()
{}
mythread2.h
#ifndef MYTHREAD2_H
#define MYTHREAD2_H#include <QThread>class myThread2 : public QThread
{Q_OBJECT
signals:downloaded(int);
public:myThread2();void run(){for(int i=0;i<100; i++){//p1->setValue(i);emit downloaded(i);QThread::sleep(1);}}
};#endif // MYTHREAD2_H
mythread1.cpp
#include "mythread2.h"myThread2::myThread2()
{}
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QProgressBar>
#include "mythread2.h"
#include "mythread1.h"class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = 0);~Widget();
private:QProgressBar *p1, *p2;myThread1 *t1;myThread2 *t2;
};#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QVBoxLayout>
#include <QThread>Widget::Widget(QWidget *parent): QWidget(parent)
{p1 = new QProgressBar;p2 = new QProgressBar;QVBoxLayout *vbox = new QVBoxLayout;vbox->addWidget(p1);vbox->addWidget(p2);setLayout(vbox);t1 = new myThread1;t2 = new myThread2;connect(t1, SIGNAL(downloaded(int)), p1, SLOT(setValue(int)));connect(t2, SIGNAL(downloaded(int)), p2, SLOT(setValue(int)));t1->start();t2->start();#if 0for(int i=0;i<100; i++){p1->setValue(i);QThread::sleep(1);}for(int i=0;i<100; i++){p2->setValue(i);QThread::sleep(2);}
#endif
}Widget::~Widget()
{}
注:
downloaded(不需要實現,qt實現的不是函數)
emit發送一個信號
exit 發送信號