一、线程
线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
二、Qt多线程
使用QThread类。
作用:用线程来处理那些耗时的后台操作,从而让主界面能及时响应用户的请求操作。
运行方式
QThread的启动由start()开始
·start()
函数会在被触发时开启线程,一般放在线程初始化或者被SIGNAL触发时启动。
QThread 的执行从 run()
函数的执行开始。
·run()
函数通过调用 exec()
函数来启动事件循环机制,并且在线程内部处理 Qt 的事件。
QThread 结束可以使用quit()函数。
三、Qt 互斥锁
线程互斥是指在多线程并发执行时,为避免多个线程访问共享资源时发生冲突而采取的一种机制。
导致问题产生的原因和解决方法
如果多个线程同时访问同一共享资源,可能会导致数据不一致、资源竞争和死锁等问题。为了避免这些问题,可以使用互斥锁(Mutex)来保护共享资源。互斥锁是一种同步机制,用于控制多个线程对共享资源的访问。当一个线程获得了互斥锁,其他线程就无法获得该锁,直到该线程释放互斥锁为止。
四、多线程接收数据
在进行基于通信对软件进行开发时,往往会出现数据从不同的端口传过来,且数据量可能很大,此时光靠主线程没有办法做到实时处理数据,此时可以使用线程进行异步处理。
接下来上代码,模拟两个数据(造数据的线程)送到一个接收线程中。
createdata1_thread.h
#ifndef CREATEDATA1_THREAD_H
#define CREATEDATA1_THREAD_H
#include <QThread>
#include "handledata_thread.h"
#include <QDebug>
class CreateData1_Thread:public QThread
{
public:
CreateData1_Thread(HandleData_Thread *m_pThread);
HandleData_Thread *m_pSend;
QString CreateData(QString str);
bool SendData(QString str);
~CreateData1_Thread();
private:
void run();
};
#endif // CREATEDATA1_THREAD_H
createdata1_thread.cpp
#include "createdata1_thread.h"
#include "mainthread.h"
CreateData1_Thread::CreateData1_Thread(HandleData_Thread *m_pThread)
{
start();
m_pSend=m_pThread;
}
CreateData1_Thread::~CreateData1_Thread()
{
}
QString CreateData1_Thread::CreateData(QString str)
{
str="a";
return str;
}
bool CreateData1_Thread::SendData(QString str)
{
m_pSend->ReceiverData(str);
return 1;
}
void CreateData1_Thread::run()
{
QString str;
str=CreateData(str);
while(1)
{
SendData(str);
QThread::sleep(1);
}
qDebug()<<"1runend!";
}
由于两个造数据的代码基本相同,唯一不同的是传输的字符不同。
接下来是接收数据的线程
handledata_thread.h
#ifndef HANDLEDATA_THREAD_H
#define HANDLEDATA_THREAD_H
#include <QThread>
#include <QDebug>
#include <QMutex>
class HandleData_Thread:public QThread
{
public:
HandleData_Thread();
~HandleData_Thread();
bool printData();
public slots:
bool ReceiverData(QString str);
private:
QStringList strlist;
QMutex datalock;
void run();
};
#endif // HANDLEDATA_THREAD_H
handledata_thread.cpp
#include "handledata_thread.h"
HandleData_Thread::HandleData_Thread()
{
start();
}
HandleData_Thread::~HandleData_Thread()
{
}
bool HandleData_Thread::ReceiverData(QString str)
{
datalock.lock();
strlist.append(str);
datalock.unlock();
return 1;
}
bool HandleData_Thread::printData()
{
QStringList p_str;
datalock.lock();
p_str=strlist;
datalock.unlock();
qDebug()<<p_str;
return 1;
}
void HandleData_Thread::run()
{
while(1)
{
printData();
QThread::sleep(3);
}
qDebug()<<"Hrunend!";
}
注意在接收数据的时候一定要在使用共享资源的时候加上互斥锁,避免因为冲突导致程序崩溃。由于qt输出框对于打印数据的限制,且本程序适用于学习和测试多线程各项操作故使用了QThread::sleep();
datalock.lock();
strlist.append(str);
datalock.unlock();
--------------------
datalock.lock();
p_str=strlist;
datalock.unlock();
main.h
#ifndef MAINTHREAD_H
#define MAINTHREAD_H
#include <QObject>
#include "createdata1_thread.h"
#include "createdata2_thread.h"
#include "handledata_thread.h"
#include <QDebug>
class mainThread : public QObject
{
Q_OBJECT
public:
explicit mainThread(QObject *parent = nullptr);
CreateData1_Thread *m_C1Thread;
CreateData2_Thread *m_C2Thread;
HandleData_Thread *m_HThread;
signals:
public slots:
};
#endif // MAINTHREAD_H
main.cpp
#include "mainthread.h"
mainThread::mainThread(QObject *parent) : QObject(parent)
{
}
int main()
{
mainThread *m_pThread;
m_pThread=new mainThread();
m_pThread->m_HThread=new HandleData_Thread();
m_pThread->m_C1Thread=new CreateData1_Thread(m_pThread->m_HThread);
m_pThread->m_C2Thread=new CreateData2_Thread(m_pThread->m_HThread);
while(1)
{
}
return 1;
}
在主线程中,需要注意的是我们要对线程进行初始化,一般要在线程的初始化函数中写start();,确保线程一直处于待启动或启动状态,如果需要一直启动线程,就需要保证启动线程后,线程一直处在while(1)的循环下不结束,一个start()对应一次run();所以在使用线程是要确保你进行操作的线程是你一直使用的线程,而不是通过不断初始化或者start()的线程,如果不断初始化或者不断start()可能会因为内存不够或者内存冲突导致程序崩溃。
最后是输出的结果:
()
("a", "b", "a", "b", "a", "b")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b")
("a", "b", "a", "b", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "a", "b", "b", "a", "b", "a", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a", "a", "b", "b", "a")
可以看出接收线程的贡献数据并不是被轮流使用的,而是根据cpu对时间片进行判定随机分配的。