QThread's run method
A QThread object manages a thread, generally inherits a custom class from QThread, implements the run method, and implements the tasks that threads need to complete in the run function. QThread itself defines two signals, starting() and finish(). The started() signal is transmitted before execution begins, and the finished() signal is transmitted when the thread is about to end.
class WorkerThread : public QThread { Q_OBJECT void run() override { // TODO emit sigMsg(result); } signals: void sigMsg(const QString &s); }; void main() { WorkerThread *workerThread = new WorkerThread(this); workerThread->start(); }
Features
1. Advantages: It can communicate with the outside world through the signal slot.
2. Disadvantages: Every time you create a new thread, you need to inherit QThread to implement a new class, which is not very convenient to use.
You have to manage resources yourself, release and delete threads. And frequent creation and release will bring about relatively large memory overhead.
3. Applicable scenarios: QThread is suitable for tasks that are resident in memory.
moveToThread of QObject
Create a class MyThread that inherits QObject, put the calculation to be executed into a function doWork, then new a Qthread, and movetothread the created myThread class into the created child thread, and then start the child thread, thus implementing a child thread. Here you must call the doWork function through the signal.
class MyThread:public QObject { Q_OBJECT public slots: void doWork(){ int i=0; while(i<4){ // ToDo qDebug()<<QThread::currentThread()<<" "<<i++; } } }; class MyTest :public QObject { Q_OBJECT QThread workerThread; public: MyTest(){ MyThread* myThread = new MyThread(); // This task function cannot have a parent object, and cannot moveToThread when there is a parent object. myThread->moveToThread(&workerThread); (); connect(this,&MyTest::active,myThread,&MyThread::doWork); // Be sure to call the corresponding function through the slot function, otherwise it will still be in the main thread } ~MyTest(){ (); } signals: void active(); }; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { qDebug()<<QThread::currentThread(); ui->setupUi(this); MyTest* t = new MyTest(); t->active(); QThread::sleep(3000); t->deleteLater(); }
Features
You must call the function through the form of a slot function, be careful! The QThread object instance you create still lives on the main thread, not the child thread. So if you call the function directly, it will still run on the main thread. This method is not thread-safe.
QRunnalble's run
Inherit Qrunnable, rewrite run virtual function, and start threads using QThreadPool
class Runnable:public QRunnable { public: Runnable(); ~Runnable(); void run(); }; Runnable::Runnable():QRunnable() { } Runnable::~Runnable() { cout<<"~Runnable()"<<endl; } void Runnable::run() { cout<<"Runnable::run()thread :"<<QThread::currentThreadId()<<endl; cout<<"dosomething ...."<<endl; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); cout<<"mainthread :"<<QThread::currentThreadId()<<endl; Runnable runObj; QThreadPool::globalInstance()->start(&runObj); (); }
Features
1. There is no need to manually release resources. The QThreadPool startup thread will be automatically released after the execution is completed.
2. The signal slot cannot be used to communicate with the outside world.
3. QRunnable is suitable for thread tasks that require frequent thread creation. QRunnable can effectively reduce memory overhead.
QtConcurrent run
Programs written with QtConcurrent automatically adjust the number of threads used based on the number of available processor cores. QtConcurrent::run can easily and quickly throw tasks into child threads for execution, without inheriting any classes, and without rewriting functions. It is very simple to use. The QFuture returned by QtConcurrent::run() does not support cancellation or pause, and the returned QFuture can only be used to query the function's run/complete status and return value.
Function prototype:
QFuture<T> QtConcurrent::run(Function function, ...) QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...)
How to use
QtConcurrent::run([=]() { // TODO });
Thread synchronization
QMutex-based mutex synchronization
The purpose of QMutex is to protect an object, data structure or code segment, so only one thread can access it at the same time. If you use Mutex lock, multiple threads are blocked when accessing a piece of code, and the next thread will continue to execute after one execution is completed.
lock(): Attempt to lock mutex. If another thread has locked this mutex, this call will block until that thread unlocks it.
unlock(): Unlock
tryLock(): Attempt to lock mutex. If the lock is obtained, this function returns true. If another process has locked the mutex, the function returns false instead of waiting until the lock is available
QMutex mutex; void DebugInfo() { (); qDebug("ABC"); qDebug("DEF"); (); }
Thread synchronization based on QReadWriteLock
A read-write lock for protecting resources that can read-write access. This cable allows multiple threads to have read-only access at the same time, but once one thread wants to write to the resource, all other threads must be blocked until the write is completed.
QReadWriteLock lock; void ReaderThread::run() { ... (); read_file(); (); ... } void WriterThread::run() { ... (); write_file(); (); ... }
void lockForRead(): Lock the read lock. If another thread is locked for writing, this function blocks the current thread. If the thread has locked the write, the read cannot be locked. void lockForWrite(): Lock the write lock. If another thread (including the current thread) has locked read or written, this function will block the current thread. If the thread is already locked for read, it will not be locked for write.
Thread synchronization based on QWaitCondition
QWaitCondition allows threads to wake up another thread when certain situations occur. One or more threads can block and wait for a QWaitCondition, and set a condition with wakeOne() or wakeAll(). wakeOne() randomly wakes up one, wakeAll() wakes up all
const int DataSize = 100000; const int BufferSize = 8192; char buffer[BufferSize]; QWaitCondition bufferNotEmpty; QWaitCondition bufferNotFull; QMutex mutex; int numUsedBytes = 0; class Producer : public QThread { public: void run(); }; void Producer::run() { qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); for (int i = 0; i < DataSize; ++i) { (); if (numUsedBytes == BufferSize) (&mutex); (); buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4]; (); ++numUsedBytes; (); (); } } class Consumer : public QThread { public: void run(); }; void Consumer::run() { for (int i = 0; i < DataSize; ++i) { (); if (numUsedBytes == 0) (&mutex); (); fprintf(stderr, "%c", buffer[i % BufferSize]); (); --numUsedBytes; (); (); } fprintf(stderr, "\n"); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); Producer producer; Consumer consumer; (); (); (); (); return 0; }
This is the article about this article about how Qt multithreading can be learned about the implementation of Qt multithreading. For more related Qt multithreading content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!