Qt中的线程是与平台无关的,使用QThread 来管理线程。
我们将处于调用main()函数的那个线程,并且由QCoreApplication::exec()创建开启的那个事件循环称为主事件循环,或者直接叫主循环。注意,
QCoreApplication::exec()只能在调用main()函数的线程调用。主循环所在的线程就是主线程,也被成为 GUI线程,因为所有有关 GUI 的操作都必须
在这个线程进行。QThread的局部事件循环则可以通过在QThread::run()中调用QThread::exec()开启
要使用QThread开始一个线程,我们可以创建它的一个子类,然后覆盖其QThread::run()函数。
线程启动
通过调用start()函数开始执行该线程,start()会默认调用run()函数。
线程退出
线程的退出调用exit()(exec返回值为0表示成功)、quit()、terminate()。线程会在开始、结束、终止时发送started()、finished()信号和terminated()等信号。quit()==exit(0)
线程睡眠
QThread提供了一些睡眠函数:sleep()精度为秒,msleep(),usleep();可以使用wait()函数来阻塞直到线程结束执行。
线程状态
使用isFinished()和isRuning()来查询线程状态。静态函数currentThreadId()和currentThread()可以返回当前执行的线程标
识符,前者返回一个系统的ID,后者返回Thread指针。
注意线程中无法使用部件类。
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
protected:
void run();
private:
volatile bool stopped; //使用了关键字 可以让其任何时候保持着最新值
}
Thread *thread = new Thread;thread->start(); // 使用 start() 开始新的线程
void MyThread::run() //start后自动执行{
while (!stopped) {
}
stopped = false;}
线程同步方法
QMutex 提供相互排斥的锁,或互斥量。QMetex提供了lock和Unlock函数,如果一个已经锁定这个互斥量,只有这个线程unlock后其它线程才可以访问。定义QMutex qm;使用qm.lock()函数与qm.unlock()函数。
QMutexLocker 可以自动对QMutex加锁与解锁,使用QMutexLocker locker(&qm);
QReadWirterLock 提供了一个可以同时读操作的,但是写操作时阻塞所有读操作。
QReadWriteLock lock ;
lock .lockForRead(); //为读而锁 lock .lockForWrite();//为写而锁
````` ········
lock .unlock(); lock .unlock();
QreadLocker与QwriteLocker可以自动对QReadWriteLock加锁与解锁
QReadLocker locker(&lock); 与 等价于 lock.lockForRead(); lock.unlock();
QSempHore提供了一个整形信号量,是QMutex的一般化,用来保护一定数量的资源,而QMutex只能保护一个
QSemaphore sem; sem.acquire();//获取信号量 sem.release(); //释放信号量
QWaitCondition即条件变量,允许一个线程可以在被另外线程唤醒之前一直休眠
多线程注意的问题:线程和 QObject
线程的事件循环用于为线程中的所有QObjects对象分发事件;默认情况下,这些对象包括线程中创建的所有对象,或者是在别处创建完成后被移动
到该线程的对象我们说,一个QObject的所依附的线程(thread affinity)是指它所在的那个线程。调用QObject::thread()可以查询一个QObject的线
程依附性。它同样适用于在QThread的构造函数中构建的对象:对象不在MyThread所表示的线程,而是在创建了MyThread的那个线程中。