Qt学习笔记 线程(一)

Qt中的线程是与平台无关的

QThread 提供了创建一个新线程的方法

新建一个线程,继承QThread并重写它的run()当调用 start()函数时会调用重载的run()函数

例:

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>

class MyThread : public QThread
{
    Q_OBJECT
public:
    bool stop ;
    explicit MyThread(QObject *parent = 0);
    void run();
signals:

public slots:

};
#endif // MYTHREAD_H
#include "mythread.h"
#include<QDebug>
MyThread::MyThread(QObject *parent) :
    QThread(parent)
{
    stop = false;
}
void MyThread::run()
{
    for(int i=0;i<1000;i++)
    {
        if(stop)break;
        qDebug()<<i;
        QThread::sleep(1);
    }
}
#include <QCoreApplication>
#include "myobject.h"
#include <QThread>
#include<QDebug>
#include "mythread.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    MyThread myThread;
    myThread.start();
    QThread::sleep(10);
    myThread.stop=true;
    return a.exec();
}

 

看一下Qt中包含的线程类:

QThread 所有线程的基类,提供了创建一个线程的方法

QThreadStorge 提供一逐线程数据存储

QMutex 提供相互排斥的锁,或互斥量

QMutexLocker 可以自动对QMutex加锁与解锁

QReadWirterLock 提供了一个可以同时读操作的锁

QreadLocker与QwriteLocker可以自动对QReadWriteLock加锁与解锁 

QSempHore提供了一个整形信号量,是互斥的泛化

QWaitCondition提供了一种方法,使线程可以在被另外线程唤醒之前一直休眠

线程的同步

QMutex 提供相互排斥的锁,或互斥量

QMetex提供了lock和Unlock函数,如果 一个已经锁定 这个互斥量,只有这个线程unlock后其它线程才可以

访问

把上边的例子做一下修改,只是为了方便大家理解,这个例子没什么作用

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>

class QMutex;
class MyThread : public QThread
{
    Q_OBJECT
private:
    QMutex qm;
    bool stop;
public:
    explicit MyThread(QObject *parent = 0);
    void run();
    void SetFlg(bool flg);
signals:
public slots:

};
#endif // MYTHREAD_H
#include "mythread.h"
#include<QDebug>
#include<QMutex>
MyThread::MyThread(QObject *parent) :
    QThread(parent)
{
    stop = false;
}
void MyThread::SetFlg(bool flg)
{
    qm.lock();
    stop=flg;
    qm.unlock();
}

void MyThread::run()
{
    for(int i=0;i<1000;i++)
    {
        qm.lock();
        if(stop)
        {
            qm.unlock();
            break;
        }
        qDebug()<<i;
        QThread::sleep(1);
        qm.unlock();
    }
}
#include <QCoreApplication>
#include "myobject.h"
#include <QThread>
#include<QDebug>
#include "mythread.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    MyThread myThread;
    myThread.start();
    QThread::sleep(10);
    myThread.SetFlg(true);
    return a.exec();
}

使用QMutex时要小心因为如果 lock()后没有unlock()会导致死锁别的线程就

永远也不能访问资源了

Qt提供了QMutexLocker来解决这个问题

修改我们的app文件

#include "mythread.h"
#include<QDebug>
#include<QMutex>
#include<QMutexLocker>
MyThread::MyThread(QObject *parent) :
    QThread(parent)
{
    stop = false;
}
void MyThread::SetFlg(bool flg)
{
    QMutexLocker locker(&qm);
    stop=flg;
}

void MyThread::run()
{
    QMutexLocker locker(&qm);
    for(int i=0;i<1000;i++)
    {
        if(stop)
        {
            break;
        }
        qDebug()<<i;
        QThread::sleep(1);

    }
}

QMutexLocker会自己unluck

QMutexLocker也提供了一个mutex()成员函数返回QMutexLocker操作的互斥量。对于需要访问互斥量是十分有用的,比如QWaitCondition::wait()。

QReadWirterLock 

用mutext进行线程同步有一个问题某个时刻只许一个线程访问资源如果同时有多个线程对共享资源进行访问,

同时有写操作线程那么这种情况下采用mutex就会成为程序的瓶颈。使用QReadWriteLock来实现多线程

读操作,一个线程写操作,写线程执行时会阻塞所有的读线程,而读线程运行不需要进行同步

QReadWriteLock lock;

void ReaderThread::run()
{
    ...
    lock.lockForRead();
    read_file();
    lock.unlock();
    ...
}

void WriterThread::run()
{
    ...
    lock.lockForWrite();
    write_file();
    lock.unlock();
    ...
}

QreadLocker和QWriteLocker类是对QReadWirterLock 的简化

它们会自动unluck();

QReadWriteLock lock;

QByteArray readData()
{
    QReadLocker locker(&lock);
    ...
    return data;
}

相当于QReadWirterLock 的写法如下

QReadWriteLock lock;

QByteArray readData()
{
    lock.lockForRead();
    ...
    lock.unlock();
    return data;
}

 

 

 

时间: 2024-10-26 17:06:14

Qt学习笔记 线程(一)的相关文章

Qt学习笔记 ListWidget的增删改

学习了一下ListWidget控件的使用,做一个小功能增删改 先把代码分解最后给出完整代码 在窗体上添加一个ListWidget 一个Horizontal Specer和  三个PushButton 效果如下 因为构造函数中的SetupUi(this)会自动将符合on_objectName_signalName()命名 的任意槽与相应的objectName的signalName()信号连接到一起 我就直接在.h文件里添加槽的声明  private slots: void on_btn_AddEv

《Java并发编程实战》学习笔记 线程安全、共享对象和组合对象

第一章 介绍 线程的优势: 充分利用多处理器 简化模型 简化异步事件的处理 提供用户界面的响应(时间) 线程的风险: 安全的风险(不好的事情会发生),提高错误出现的几率 活性的风险(好的事情不会发生),如某些代码不会执行,出现死锁.活锁以及饥饿 性能的风险,不好的多线程编程可能会危害性能 第二章 线程安全 编写线程安全的代码,实质是管理对状态的访问,尤其是那些共享.可变的状态.对象的状态包括任何能影响它外部可见行为的数据. 当有过个线程能访问状态变量时,而且他们当中能对变量进行修改,则需要对他们

【Qt编程】Qt学习笔记&amp;lt;三&amp;gt;

1.      如果程序中使用了png以外格式的图片,在发布程序时就要将Qt安装目录下plugins中的imagineformats文件复制到发布文件中. 2.      在函数声明处快速添加函数定义可单击函数名,按下alt+Enter键后,按下Enter键就可以进入到函数定义部分. 3.      关联槽和信号的两种方法:1.直接在设计器中用鼠标拖拽,适合于设计器中的部件间进行.2.在设计器中右击部件进入转到槽,这种方法是自动关联. 4.      我们在进行编程时,应注意:一个文件.一个类.

Qt 学习笔记 TreeWidget 增删改

在窗体上放一个TreeWidget控件和四个PushButton加一个Horizontal Spacer 布局如图 给树添加元素节点的方法和实现 .h文件 QTreeWidgetItem * AddTreeRoot(QString name,QString desc); QTreeWidgetItem * AddTreeNode(QTreeWidgetItem *parent,QString name,QString desc); .cpp文件 QTreeWidgetItem * TreeVie

Qt学习笔记 TableWidget使用说明和增删改操作的实现

看一下效果很简单的一个小功能 先说分部讲一下过程 再给出详细代码  添加数据 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->tableWidget->setColumnCount(2); ui->tableWidget->setRowCount(2); ui->tableWidget->se

Qt学习笔记网络(一)

Qt5 移除了QHttp是因为功能重复 用QNetworkAccessManager完全能搞定 新建一个控制台应用程序 看一下QNetworkAccessManager的帮助文档 需要添加Qt + =network 新建一个类 .h文件 #ifndef DOWNPAGES_H #define DOWNPAGES_H #include<QNetworkAccessManager> #include <QObject> class DownPages : public QObject

Qt学习笔记常用容器

主要说Qt的以下几种容器 1.QList<T> 2.QLinkedList<T> 3.Map<T> 和一些常用的容器方法的使用 qSort qCopy qFind 1.QList<T>泛型集合是最常用的一种容器 看一下它的常用 操作 添加删除和两个迭代器 QListIterator和QMutableListIterator #include <QCoreApplication> #include<QList> #include<

Qt学习笔记 QMessageBox

Qt的几种MessageBox 1.Infomation类型 QMessageBox::information(this,tr("hello"),tr("title")); 2.Question类型 QMessageBox::StandardButton returnBtn; returnBtn = QMessageBox::question(this,tr("hello have problem?"),tr("error!"

Qt学习笔记 信号和槽

槽和普通c++成员函数一样只可以为虚函数,也可以被重用,可以是公有的也可以是私有的,也可以被其它的c++函数调用; 参数也是任意的 唯一不同的是本槽和信号是可以连在一起的,和c#的事件差不多.相连后每当发射这个信号后就会自动调用这个槽 connection(sender,SIGNAL(signal),receiver,SLOT(slot)); sender就发送信号的Qobject指针 receiver是槽的Qobject指针 signal和slot是只有形参的函数名.SIGNAL和SLOT宏会