lv20 QT进程线程编程

知识点:启动进程 ,线程 ,线程同步互斥

1 启动进程

应用场景:通常在qt中打开另一个程序

process模板

QString program = "/bin/ls";
QStringList arguments;
arguments << "-l" << "-a";

QProcess *myProcess = new QProcess(parent);
myProcess->execute(program, arguments);

示例:

widget.h

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QFileDialog>
#include <QProcess>
#include <QStringList>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
public slots:
    void showfile()
    {
        QString filename = QFileDialog::getOpenFileName();
        le->setText(filename);

        QStringList arg = {filename};
        QProcess ppp;
        ppp.execute("notepad", arg);
    }

private:
    QLineEdit *le;
    QPushButton *pb;
};

#endif // WIDGET_H

widget.cpp

cpp 复制代码
#include "widget.h"
#include <QVBoxLayout>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    le = new QLineEdit;
    pb = new QPushButton("showtxt");

    QVBoxLayout *vbox = new QVBoxLayout;
    vbox->addWidget(le);
    vbox->addWidget(pb);
    setLayout(vbox);

    connect(pb, SIGNAL(clicked(bool)), this, SLOT(showfile()));
}

Widget::~Widget()
{

}

效果在qt中使用文本编辑器打开一个文本。

2 线程

应用场景:启动一个线程和进程来辅助程序

线程:

class WorkerThread : public Qthread{
Q_OBJECT
      void run() {
	/* ... here is the expensive or blocking operation ... */
          emit resultReady(result);
      }
signals:
      void resultReady(const QString &s);
  };
WorkerThread   x;
x.start();
  • void run()方法:这是QThread的一个虚函数,你需要在子类中重写它以实现线程的任务。当调用线程的start()方法时,这里的代码将在新的线程中执行。

  • void resultReady(const QString &s)信号:这是一个自定义信号,当线程完成工作并有结果可供返回时,将通过emit关键字发射这个信号。

  • QT是信号驱动、或者异步驱动的框架,平时app需要执行到a.exec()才会执行

**双线程示例:**一个线程打印数组,一个线程排序数组

thread_show.h(继承QThread类)

cpp 复制代码
#ifndef THREAD_SHOW_H
#define THREAD_SHOW_H

#include <Qthread>
#include <QDebug>
#include <QMutex>

class thread_show : public QThread
{
    Q_OBJECT
public:
    thread_show(char *p):m_arr(p){}

    void run()   //这是QThread的一个虚函数(qt中斜线表示),你需要在子类中重写它以实现线程的任务。当调用线程的start()方法时,这里的代码将在新的线程中执行。
    {
        while(1)
        {
            //lock
            qDebug()<<m_arr;
            sleep(1);
        }

    }
private:
    char *m_arr;

};

#endif // THREAD_SHOW_H

thread_show.cpp(重写构造函数)

cpp 复制代码
#include "thread_show.h"

/*
thread_show::thread_show()
{

}
*/

thread_rev.h

cpp 复制代码
#ifndef THREAD_REV_H
#define THREAD_REV_H

#include <QThread>

class thread_rev : public QThread
{
    Q_OBJECT
public:
    thread_rev(char *p):m_arr(p){}  //构造时,直接赋值效率高

    void run()
    {
       while(1)
       {
           for(int i=0; i<5; i++)
           {
               m_arr[i] ^= m_arr[9-i];
               m_arr[9-i] ^= m_arr[i];
               m_arr[i] ^= m_arr[9-i];
           }
       }
    }
private:
    char *m_arr;
};

#endif // THREAD_REV_H

thread_rev.cpp(重写构造函数)

cpp 复制代码
#include "thread_rev.h"

/*
thread_rev::thread_rev()
{

}
*/

main.cpp

cpp 复制代码
#include "widget.h"
#include <QApplication>
#include "thread_rev.h"
#include "thread_show.h"


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    char arr[] = "0123456789";

    thread_show t1(arr);  //打印
    thread_rev t2(arr);   //翻转数组

    t1.start();
    t2.start();

    return a.exec();
}

效果:两个线程同时操作,打印出来的数组无规律

3 线程互斥

官方示例

QSemaphore :
 QSemaphore sem(5);      // sem.available() == 5
  sem.acquire(3);         // sem.available() == 2
  sem.acquire(2);         // sem.available() == 0
  sem.release(5);         // sem.available() == 5
  sem.release(5);         // sem.available() == 10
  sem.tryAcquire(1);      // sem.available() == 9, returns true
  sem.tryAcquire(250);    // sem.available() == 9, returns false

QMutex ://locker
 QMutex mutex;
  void method1(){
      mutex.lock();
      mutex.unlock();
  }
  void method2(){
      mutex.lock();
      mutex.unlock();
  }

实验示例:

thread_show.h

cpp 复制代码
#ifndef THREAD_SHOW_H
#define THREAD_SHOW_H

#include <Qthread>
#include <QDebug>
#include <QMutex>

class thread_show : public QThread
{
    Q_OBJECT
public:
    thread_show(char *p, QMutex *l):m_arr(p), m_arrlock(l){}

    void run()   //这是QThread的一个虚函数(qt中斜线表示),你需要在子类中重写它以实现线程的任务。当调用线程的start()方法时,这里的代码将在新的线程中执行。
    {
        while(1)
        {

            m_arrlock->lock();
            qDebug()<<m_arr;
            m_arrlock->unlock();
            sleep(1);
        }

    }
private:
    char *m_arr;
    QMutex *m_arrlock;

};

#endif // THREAD_SHOW_H

thread_show.cpp

cpp 复制代码
#include "thread_show.h"

/*
thread_show::thread_show()
{

}
*/

thread_rev.h

cpp 复制代码
#ifndef THREAD_REV_H
#define THREAD_REV_H

#include <QThread>
#include <QMutex>

class thread_rev : public QThread
{
    Q_OBJECT
public:
    thread_rev(char *p, QMutex *l):m_arr(p), m_arrlock(l){}

    void run()
    {
       while(1)
       {
           m_arrlock->lock();
           for(int i=0; i<5; i++)
           {
               m_arr[i] ^= m_arr[9-i];
               m_arr[9-i] ^= m_arr[i];
               m_arr[i] ^= m_arr[9-i];
           }
           m_arrlock->unlock();
       }
    }
private:
    char *m_arr;
    QMutex *m_arrlock;

};

#endif // THREAD_REV_H

thread_rev.cpp

cpp 复制代码
#include "thread_rev.h"

/*
thread_rev::thread_rev()
{

}
*/

main.cpp

cpp 复制代码
#include "widget.h"
#include <QApplication>
#include "thread_rev.h"
#include "thread_show.h"
#include <QMutex>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    char arr[] = "0123456789";
    QMutex arr_lock;

    thread_show t1(arr,&arr_lock);  //打印
    thread_rev t2(arr,&arr_lock);   //翻转数组

    t1.start();
    t2.start();

    return a.exec();
}

效果:两个线程同时操作,打印出来的数组均为排序后的结果,排序中不会受到干扰

4 线程同步

目的:实现一个线程获取资源需要等另一个线程释放资源。

thread_hello.h

cpp 复制代码
#ifndef THREAD_HELLO_H
#define THREAD_HELLO_H

#include <QSemaphore>
#include <QThread>
#include <QDebug>

class thread_hello : public QThread
{
    Q_OBJECT
public:
    thread_hello(QSemaphore *s):sem(s){ }

    void run()
    {
        while(1)
        {
            qDebug()<<"hello";
            sleep(1);

            //V
            sem->release();
        }

    }
private:
    QSemaphore *sem;
};

#endif // THREAD_HELLO_H

thread_hello.cpp

cpp 复制代码
#include "thread_hello.h"

/*
thread_hello::thread_hello()
{

}
*/

thread_world.h

cpp 复制代码
#ifndef THREAD_WORLD_H
#define THREAD_WORLD_H

#include <QThread>
#include <QDebug>
#include <QSemaphore>

class thread_world : public QThread
{
    Q_OBJECT
public:
    thread_world(QSemaphore *s):sem(s){ }

    void run()  //字体歪的就是虚函数
    {
        while(1)
        {
            //P
            sem->acquire();
            qDebug()<<"world";
        }

    }
private:
    QSemaphore *sem;
};

#endif // THREAD_WORLD_H

thread_world.cpp

cpp 复制代码
#include "thread_hello.h"

/*
thread_hello::thread_hello()
{

}
*/

main.cpp

cpp 复制代码
#include <QCoreApplication>
#include "thread_hello.h"
#include "thread_world.h"
#include <QSemaphore>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QSemaphore sem;
    thread_hello hello(&sem);
    thread_world world(&sem);

    hello.start();
    world.start();

    return a.exec();
}

效果,hello先打印,才会有world。

综合示例:实现两个进度条在下载

mythread1.h

cpp 复制代码
#ifndef MYTHREAD1_H
#define MYTHREAD1_H

#include <QThread>

class myThread1 : public QThread
{
    Q_OBJECT
signals:
    downloaded(int);
public:
    myThread1();

    void run()
    {
        for(int i=0;i<100; i++)
        {
            //p1->setValue(i);
            emit downloaded(i);
            QThread::sleep(2);
        }
    }
};

#endif // MYTHREAD1_H

mythread1.cpp

cpp 复制代码
#include "mythread1.h"

myThread1::myThread1()
{

}

mythread2.h

cpp 复制代码
#ifndef MYTHREAD2_H
#define MYTHREAD2_H

#include <QThread>

class myThread2 : public QThread
{
    Q_OBJECT
signals:
    downloaded(int);
public:
    myThread2();

    void run()
    {
        for(int i=0;i<100; i++)
        {
            //p1->setValue(i);
            emit downloaded(i);
            QThread::sleep(1);
        }
    }
};

#endif // MYTHREAD2_H

mythread1.cpp

cpp 复制代码
#include "mythread2.h"

myThread2::myThread2()
{

}

widget.h

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QProgressBar>
#include "mythread2.h"
#include "mythread1.h"


class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
private:
    QProgressBar *p1, *p2;

    myThread1 *t1;
    myThread2 *t2;
};

#endif // WIDGET_H

widget.cpp

cpp 复制代码
#include "widget.h"
#include <QVBoxLayout>
#include <QThread>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    p1 = new QProgressBar;
    p2 = new QProgressBar;

    QVBoxLayout *vbox = new QVBoxLayout;
    vbox->addWidget(p1);
    vbox->addWidget(p2);
    setLayout(vbox);

    t1 = new myThread1;
    t2 = new myThread2;
    connect(t1, SIGNAL(downloaded(int)), p1, SLOT(setValue(int)));
    connect(t2, SIGNAL(downloaded(int)), p2, SLOT(setValue(int)));
    t1->start();
    t2->start();

#if 0
    for(int i=0;i<100; i++)
    {
        p1->setValue(i);
        QThread::sleep(1);
    }

    for(int i=0;i<100; i++)
    {
        p2->setValue(i);
        QThread::sleep(2);
    }
#endif
}

Widget::~Widget()
{

}

注:

downloaded(不需要实现,qt实现的不是函数)

emit发送一个信号

exit 发送信号

相关推荐
PythonFun17 分钟前
Python批量下载PPT模块并实现自动解压
开发语言·python·powerpoint
Death20021 分钟前
Qt 6 相比 Qt 5 的主要提升与更新
开发语言·c++·qt·交互·数据可视化
机器视觉知识推荐、就业指导23 分钟前
使用Qt实现实时数据动态绘制的折线图示例
开发语言·qt
快乐就好ya1 小时前
Java多线程
java·开发语言
CS_GaoMing2 小时前
Centos7 JDK 多版本管理与 Maven 构建问题和注意!
java·开发语言·maven·centos7·java多版本
2401_858120533 小时前
Spring Boot框架下的大学生就业招聘平台
java·开发语言
转调3 小时前
每日一练:地下城游戏
开发语言·c++·算法·leetcode
Java探秘者3 小时前
Maven下载、安装与环境配置详解:从零开始搭建高效Java开发环境
java·开发语言·数据库·spring boot·spring cloud·maven·idea
2303_812044463 小时前
Bean,看到P188没看了与maven
java·开发语言
秋夫人3 小时前
idea 同一个项目不同模块如何设置不同的jdk版本
java·开发语言·intellij-idea