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

相关推荐
愚润求学20 分钟前
【C++】vector常用方法总结
开发语言·c++·vector
天天进步201530 分钟前
Python项目-基于Flask的个人博客系统设计与实现(1)
开发语言·python·flask
安然无虞32 分钟前
31天Python入门——第20天:魔法方法详解
开发语言·后端·爬虫·python
QQ__176461982436 分钟前
Matlab安装tdms插件
开发语言·matlab·tdms插件
画个逗号给明天"38 分钟前
C#从入门到精通(5)
开发语言·笔记·c#
赤秀1 小时前
C++模板初阶
开发语言·c++
橘猫云计算机设计1 小时前
基于JavaWeb的二手图书交易系统(源码+lw+部署文档+讲解),源码可白嫖!
java·开发语言·前端·毕业设计·php
半桔1 小时前
红黑树剖析
c语言·开发语言·数据结构·c++·后端·算法
江烽渔火2 小时前
C++ 多态
开发语言·c++
嘤国大力士2 小时前
C++11&QT复习 (十)
java·c++·qt