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

#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

#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类)

#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(重写构造函数)

#include "thread_show.h"

/*
thread_show::thread_show()
{

}
*/

thread_rev.h

#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(重写构造函数)

#include "thread_rev.h"

/*
thread_rev::thread_rev()
{

}
*/

main.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

#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

#include "thread_show.h"

/*
thread_show::thread_show()
{

}
*/

thread_rev.h

#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

#include "thread_rev.h"

/*
thread_rev::thread_rev()
{

}
*/

main.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

#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

#include "thread_hello.h"

/*
thread_hello::thread_hello()
{

}
*/

thread_world.h

#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

#include "thread_hello.h"

/*
thread_hello::thread_hello()
{

}
*/

main.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

#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

#include "mythread1.h"

myThread1::myThread1()
{

}

mythread2.h

#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

#include "mythread2.h"

myThread2::myThread2()
{

}

widget.h

#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

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

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

4IOT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值