线程
线程分为gui线程(主线程)和次要线程,涉及gui的必须在主线程
线程的同步
两个线程可以同时访问一个对象,试想如果一个对象同时执行两种方法则可能出错
QMutex 是强制执行互斥的基本类。一个线程锁定一个互斥量(mutex),以获得共享资源的访问权限。如果另一个线程试图锁定互斥量,而互斥量已被锁定,这时,它将进入睡眠状态,直到第一个线程完成其任务并解锁互斥量。
QReadWriteLock 类似于 QMutex,除了它区分了“读”和“写”的访问。当一个数据块没有被写入,多线程对他同时进行读取是安全的。一个 QMutex 迫使轮流读取共享数据,而 QReadWriteLock 允许同时读取,从而提高并行性。
QSemaphore 是 QMutex 的一个推广,可以保护一定数量相同的资源。相比之下,一个 QMutex 只能保护一个资源
QWaitCondition 同步线程,不通过执行互斥,而通过提供一个条件变量。其它原语使线程等待,直到资源被解锁
QMutexLocker、QReadLocker 和 QWriteLocker 是便利类,使其更易于使用 QMutex 和QReadWriteLock 。当他们被构建时,就会锁定资源;当被销毁时,就会自动解锁。设计他们是为了简化使用 QMutex 和 QReadWriteLock 的代码,从而减少资源被永久锁定的可能性。
线程安全的可重入类
注意点:
1.事件的驱动对象只能被使用在单线程中,也就是不能在此线程中引用别的线程的socket或者定时器之类的
2.gui类是不可重入的,只能放在主线程中
class Counter
{
public:
Counter() {
n = 0; }
void increment() {
QMutexLocker locker(&mutex); ++n; }//局部变量locker销毁时mutex被释放相当于unlock了
void decrement() {
QMutexLocker locker(&mutex); --n; }
int value() const {
QMutexLocker locker(&mutex); return n; }
private:
mutable QMutex mutex;//由于const,所以加mutable,可修改
int n;
};
**QObject::moveToThread()**函数改变一个对象和它的孩子的线程所属性。
从另一个线程(不是该QObject对象所属的线程)对该QObject对象调用delete方法是不安全的,除非你能保证该对象在那个时刻不处理事件,使用QObejct::deleteLater()更好。一个DeferredDelete类型的事件将被提交(posted),而该对象的线程的事件循环最终会处理这个事件。默认情况下,拥有一个QObject的线程就是创建QObject的那个线程,而不是QObject::moveToThread()被调用后的。
QCoreApplication::postEvent(),你可以在任何时刻给任何线程中的任何对象发送事件,这些事件将自动被分发到该对象所被创建的线程事件循环中。
**QCoreApplication::sendEvent()**不同于postEvent())只能将事件分发到和该函数调用者相同的线程中的对象。
可以在QThread::run()的实现中安全地发射信号,因为信号发射是线程安全的或者必须用一个mutex保护对该QObject子类的内部数据的所有访问
QtConcurrent
该QtConcurrent命名空间提供高层次的API,使人们可以编写多线程程序,而无需使用低级线程原语。
Header: #include
qmake: QT += concurrent
/*
*QStringList lowerCaseStrings = QtConcurrent::blockingFiltered(strlist, allLowerCase);//返回序列
* QtConcurrent::blockingFilter(strlist, allLowerCase);//直接修改
*/
bool allLowerCase(const QString &str)
{
return str.toLower()==str;
}
void addToDictionary(QString &dictionary, const QString &string)
{
dictionary.append(string);
}
GuiTest::GuiTest(QWidget *parent)
: QMainWindow(parent)
{
QStringList strlist;
strlist<<"zylg1"<<"zylg2"<<"123"<<"ZYLG"<<"Zylg";
foreach(QString str ,strlist)cout<<str<<"\t";cout<<endl;
QStringList lowerCaseStrings = QtConcurrent::blockingFiltered(strlist, allLowerCase);//返回序列
QFuture<QString> dictionary = QtConcurrent::filteredReduced(strlist, allLowerCase, addToDictionary);
QtConcurrent::blockingFilter(strlist, allLowerCase);//直接修改
foreach(QString str ,strlist)cout<<str<<"\t";cout<<endl;
foreach(QString str ,lowerCaseStrings)cout<<str<<"\t";cout<<endl;
foreach(QString str ,dictionary)cout<<str<<"\t";cout<<endl;
}
/*
* result:
* zylg1 zylg2 123 ZYLG Zylg
* zylg1 zylg2 123
* zylg1 zylg2 123
* zylg1zylg2123
*/
QImage scaled(const QImage &image)
{
return image.scaled(100, 100);
}
QList<QImage> images = ...;
QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scaled);
//void QtConcurrent::blockingMap(Iterator begin, Iterator end, MapFunctor function)
//QList<int> ints = QtConcurrent::blockingMapped<QList<int> >(beginIterator, endIterator, fn);
#include<QTextStream>
#include<QtConcurrent>
#