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 发送信号

相关推荐
Swift社区1 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht1 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht2 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20242 小时前
Swift 数组
开发语言
stm 学习ing3 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
湫ccc3 小时前
《Python基础》之字符串格式化输出
开发语言·python
mqiqe4 小时前
Python MySQL通过Binlog 获取变更记录 恢复数据
开发语言·python·mysql
AttackingLin4 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python