Qt进程和线程

1. 进程 QProcess

1.1 知识点

在c语言中:

使用fork函数,由当前进程创建一个子进程,fork的子进程和父进程代码完全一致

在QT中:

QProcess类:额外执行的程序,执行程序后就是一个新的进程执行

QProcess:进程管理类,使用QProcess类可以操作进程

start(程序的路径):启动进程

注意

一个进程管理对象同时只能创建一个进程执行,当被管理的进程结束,可以启动下一个进程执行

1.2信号

绑定started() 信号,这个信号用来判断进程是否创建成功

绑定finished(int,QProcess::ExitStatus)信号,判断进程是否结束

绑定readyRead()信号,判断进程是否产生数据

1.3 举例

Qt进程和线程_第1张图片

process

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();
    //启动是否成功的槽
    void process_started();

    //判断进程是否结束的槽
    void process_finshed();

    //判断进程是否产生数据的槽
    void process_readyRead();

private:
    Ui::MainWindow *ui;

    QProcess* process;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

//进程的使用
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //创建进程管理对象
    process = new QProcess;

    //绑定started() 信号,这个信号用来判断进程是否创建成功
    connect(process,SIGNAL(started()),this,SLOT(process_started()));

    //绑定finished(int,QProcess::ExitStatus)信号,判断进程是否结束
    connect(process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(process_finshed()));

    //绑定readyRead()信号,判断进程是否产生数据
    connect(process,SIGNAL(readyRead()),this,SLOT(process_readyRead()));

}

MainWindow::~MainWindow()
{
    delete ui;
}


//启动一个新的进程
void MainWindow::on_pushButton_clicked()
{
    //启动进程
    //start()的参数要传一个路径,比如输入“notepad”,会打开一个新的记事本出来
    //重点:一个进程管理对象只能创建一个进程,当被管理进程结束,就可以创建新的进程了
    process->start(ui->lineEdit->text());



}

//是否启动成功
void MainWindow::process_started(){
    qDebug()<<"进程启动成功";
    ui->textEdit->append("创建成功");

}

//判断进程是否结束
void MainWindow::process_finshed(){
    qDebug()<<"进程结束";

    ui->textEdit->append("进程结束");
}

//判断进程是否产生数据,当有数据产生,就读取
void MainWindow::process_readyRead(){
    //在进程产生数据时,读取该进程的数据
    QByteArray data =  process->readAll();
    ui->textEdit->append(data);
}

Qt进程和线程_第2张图片

Qt进程和线程_第3张图片

2. 进程间通信 QSharedMemory

2.1 知识点

核心思想就是使用  QSharedMemory:共享内存

2.2 举例

发送端

Qt进程和线程_第4张图片

process_write

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    //创建共享内存对象
    QSharedMemory* shm;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //共享内存对象,并指定共内存id
    shm = new QSharedMemory("hqyj");
    //可以这样设置共内存id
//    shm->setKey();

    //创建并映射共享内存,1024是共享内存大小
    shm->create(1024);
    //单独映射也可以
//    shm->attach();

}

Widget::~Widget()
{
    delete ui;
}


//往共享内存中写
void Widget::on_pushButton_clicked()
{
    //获取共享内存首地址
    void* pdata =  shm->data();

    QString src = ui->textEdit->toPlainText();
    //src.toStdString().c_str()
    //src.toStdString()转换为c++标准字符串,c_str() 函将转换为指向以空字符(\0)结尾的 C 字符串    
    memcpy((char*)pdata,src.toStdString().c_str(),1024);
}


接收端

Qt进程和线程_第5张图片

process_read

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;

    //共享内存对象
    QSharedMemory* shm;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建共享内存对象
    shm = new QSharedMemory;

    //指定共享内存的id
    shm->setKey("hqyj");

    //映射共享内存
    shm->attach();
}

Widget::~Widget()
{
    delete ui;
}

//从共享内存中读
void Widget::on_pushButton_clicked()
{
    //将共享内存拷贝到buf
    char buf[1024];
    memcpy(buf,shm->data(),1024);

    ui->textEdit->setText(QString(buf));
}


Qt进程和线程_第6张图片

3. 线程 QThread

3.1 知识点

核心思想就是,在创建一个类继承QThread,然后再新创建的类中重写run()函数执行线程,在主进程中 启动线程

线程:由进程中进行创建,在进程中额外执行一个新的任务就叫做线程。

在进程上下文切换时,系统开销比较大,多个线程在进程中,可以共享进程的资源,而调度方式和进程相同

c语言中

pthread_create(&线程id,属性对象地址,线程起始函数,线程函数的参数);

在QT中

QThread:管理线程(线程开启、线程关闭、线程执行等)

run()函数:线程的执行(当线程执行时,就是执行run函数,QThread类已经由Qt完成,run不能修改----线程任务功能固定)

通过QThread类,派生出新类,派生类 也是线程类,同时重写 run函数实现需要的线程功能,当启动线程时,就执行自己的run作为线程任务

start():启动线程

3.2 信号

Qt进程和线程_第7张图片

void finished():信号,线程结束

void started():信号,线程启动

3.3 举例

thread

Qt进程和线程_第8张图片

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_3_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::Widget *ui;

    //实例化线程对象
    thread1* t1;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"


//线程的使用
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建线程对象
    t1 = new thread1;
    t1->str = "hello world";
}

Widget::~Widget()
{
    delete ui;
}


//启动线程
void Widget::on_pushButton_clicked()
{
    //启动
    t1->start();
}

//改变线程打印的内容
void Widget::on_pushButton_3_clicked()
{
    t1->str = ui->lineEdit->text();
}

//停止线程
void Widget::on_pushButton_2_clicked()
{
    t1->stop();
}

thread1.h

#ifndef THREAD1_H
#define THREAD1_H

#include 
#include 

class thread1 : public QThread
{
    Q_OBJECT
public:
    thread1();

    //重写执行线程函数run()
    void run();

    void stop();


    QString str;

    bool ok;//循环标志位

};

#endif // THREAD1_H

thread1.cpp

#include "thread1.h"

thread1::thread1()
{
    ok = true;
}


//执行线程
void thread1::run(){
    while(ok){
        qDebug()<<"thread1打印:"<

Qt进程和线程_第9张图片

4. 互斥锁

防止在多线程环境下,多个线程对一个变量同时修改

QMutex:互斥量

QReadWriteLock:读写锁

4.1 举例

还是上面的程序

thread

thread1.h

Qt进程和线程_第10张图片

   //互斥锁变量
    QMutex* mutex;

thread1.cpp

//执行线程
void thread1::run(){
    while(ok){
        mutex->lock();//加锁
        qDebug()<<"thread1打印:"<unlock();//解锁
        sleep(1);
    }
    qDebug()<

widget.h

Qt进程和线程_第11张图片

    //互斥锁变量
    QMutex* mutex;

widget.cpp

Qt进程和线程_第12张图片

//改变线程打印的内容
void Widget::on_pushButton_3_clicked()
{
    mutex->lock();//加锁
    t1->str = ui->lineEdit->text();
    mutex->unlock();//解锁
}

Qt进程和线程_第13张图片

4.2读写锁

Qt进程和线程_第14张图片

读写锁和互斥锁差不多,思想就是

1. 如果加了读锁,别的线程也可以加读锁,但是如果要去加写锁,就必须等待读锁的释放

2. 如果加了写锁,别的线程要加锁就必须等待写锁的释放

你可能感兴趣的:(Qt,qt,c语言,c++,算法)