QT 多线程 依次执行的问题

purplepare 2017-07-17 04:33:04
QT,编写一个多线程,即开启9个线程,这九个线程的ID分别为1,2,3,4,5,6,7,8,9,每个线程将自己的ID按顺序打印到屏幕上,要求结果必须按照1,2,3,4,5,6,7,8,9...依次类推
本人刚开始接触多线程,尝试写了段程序,但是结果不对,我用计数器每隔100毫秒执行一次显示:即
主线程代码:
QMutex mutex;
void MyClass::handleProcess(){
QVector<QThread*> threads;
m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
m_timer->setTimerType(Qt::PreciseTimer);
for (int k = 0; k<3; k++){
QThread *imageThread = new QThread;
MyImage *myImage = new MyImage(k);
myImage->moveToThread(imageThread);
connect(this, SIGNAL(imageCreate()), myImage, SLOT(startImageCreate()));
threads.append(imageThread);
}
m_timer->start(100);
}
void MyClass::onTimeOut(){
for (int i = 0; i<9; i++)
threads[i]->start();
emit imageCreate();
}

子线程代码:
class MyImage : public QObject
{
Q_OBJECT
public:
explicit MyImage(int index = 0);
public slots :
void startImageCreate(int index);
private:
int index;
};
extern QMutex mutex;
MyImage::MyImage(int No) :QObject()
{
index = No ;
}

void MyImage::startImageCreate(int index)
{
mutex.lock();
qDebug() << index << " running..\n";
mutex.unlock();
}

各位大神,我的主要目的就是想依次的执行线程,请问怎么加互斥量才会解决这个问题呢,在线等,拜谢!
...全文
883 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
绝地武士007 2020-09-28
  • 打赏
  • 举报
回复
暂时只想到使用 WaitConditon 的方式,后一个线程执行的条件需要前一个线程来满足,不过比较麻烦
绝地武士007 2020-09-28
  • 打赏
  • 举报
回复
@3楼 好像还是有个问题,比如ID5的线程执行完,释放出6的资源,看起来满足了要求,此时ID6可以执行了。 但是这时如果ID4也在申请资源,那么有可能ID5之后是ID4抢到资源执行,并非希望中的ID6
purplepare 2017-07-19
  • 打赏
  • 举报
回复
你好,这个确实能够实现依次显示,但是,我发现它是阻塞的方式,也就是只有等依次显示完成,才能启动主界面,是这样的,我的程序是,每个线程中保存的数据是图像,每次九个都执行完一次后,这些图像需要在主线程里显示出来,之后九个线程在继续保存新的图像,继续在主线程里显示,我改怎么修改这种阻塞的方式呢,多谢大神~
引用 5 楼 n7zj0x8 的回复:

#include <QCoreApplication>
#include <QEventLoop>
#include <QSemaphore>
#include <QTimer>
#include <QThread>
#include <QDebug>

class MyImage : public QThread
{
    Q_OBJECT
public:
    explicit MyImage(QSemaphore *sem, int index = 0) : sem(sem), index(index){}
    ~MyImage() { this->exit(); this->wait(); }

public slots :
    void startImageCreate()
    {
        sem->acquire(index);
        qDebug() << "index:" << index;
        sem->release(index+1);

        this->exit();
    }

private:
    QSemaphore *sem;
    int index;
};

class Process1_9
{
public:
    Process1_9() : sem(1){}
    ~Process1_9(){}

    void process()
    {
        QEventLoop loop;

        QVector<MyImage*> threads;
        for (int k = 1; k <= 9; k++)
        {
            MyImage *myImage = new MyImage(&sem, k);
            if (k == 9)
            {
                QObject::connect(myImage, SIGNAL(finished()), &loop, SLOT(quit()));
            }

            threads.append(myImage);

            myImage->start();
            myImage->moveToThread(myImage);

            QTimer::singleShot(0, myImage, SLOT(startImageCreate()));
        }

        loop.exec();

        qDeleteAll(threads);
    }

private:
     QSemaphore sem;
};

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

    for (int i = 0; i < 3; ++i)
    {
        Process1_9 p;
        p.process();

        qDebug() << "===times:" << i + 1;
        QEventLoop loop;
        QTimer::singleShot(1000, &loop, SLOT(quit()));
        loop.exec();
    }

    return a.exec();
}

#include "main.moc"

就是把1-9的执行再封装一下呀. 方式很多,我随便写的.你看着修改吧.
引用 5 楼 n7zj0x8 的回复:

#include <QCoreApplication>
#include <QEventLoop>
#include <QSemaphore>
#include <QTimer>
#include <QThread>
#include <QDebug>

class MyImage : public QThread
{
    Q_OBJECT
public:
    explicit MyImage(QSemaphore *sem, int index = 0) : sem(sem), index(index){}
    ~MyImage() { this->exit(); this->wait(); }

public slots :
    void startImageCreate()
    {
        sem->acquire(index);
        qDebug() << "index:" << index;
        sem->release(index+1);

        this->exit();
    }

private:
    QSemaphore *sem;
    int index;
};

class Process1_9
{
public:
    Process1_9() : sem(1){}
    ~Process1_9(){}

    void process()
    {
        QEventLoop loop;

        QVector<MyImage*> threads;
        for (int k = 1; k <= 9; k++)
        {
            MyImage *myImage = new MyImage(&sem, k);
            if (k == 9)
            {
                QObject::connect(myImage, SIGNAL(finished()), &loop, SLOT(quit()));
            }

            threads.append(myImage);

            myImage->start();
            myImage->moveToThread(myImage);

            QTimer::singleShot(0, myImage, SLOT(startImageCreate()));
        }

        loop.exec();

        qDeleteAll(threads);
    }

private:
     QSemaphore sem;
};

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

    for (int i = 0; i < 3; ++i)
    {
        Process1_9 p;
        p.process();

        qDebug() << "===times:" << i + 1;
        QEventLoop loop;
        QTimer::singleShot(1000, &loop, SLOT(quit()));
        loop.exec();
    }

    return a.exec();
}

#include "main.moc"

就是把1-9的执行再封装一下呀. 方式很多,我随便写的.你看着修改吧.
purplepare 2017-07-18
  • 打赏
  • 举报
回复
引用 3 楼 n7zj0x8 的回复:
我给你发动了一下.相信应该可以理解. 没有使用锁,使用的信号量.它正好可以满足你的需求.


#include <QCoreApplication>
#include <QSemaphore>
#include <QTimer>
#include <QThread>
#include <QDebug>

class MyImage : public QObject
{
    Q_OBJECT
public:
    explicit MyImage(int index = 0);
public slots :
    void startImageCreate();
private:
    int index;
};
static QSemaphore sem(1);

MyImage::MyImage(int No) :QObject()
{
    index = No  ;
}

void MyImage::startImageCreate()
{
    sem.acquire(index); //获取资源,
    qDebug() << "index:" << index;
    sem.release(index+1);//释放多一个的资源,刚好可以,让下一个acquire获取成功.
}

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

    QVector<QThread*> threads;
    for (int k = 1; k <= 9; k++) //从一开始.到9结束
    {
        QThread *imageThread = new QThread;
        MyImage *myImage = new MyImage(k);

        imageThread->start(); //启动线程
        myImage->moveToThread(imageThread);

        threads.append(imageThread);

        //用QTimer来触发槽,和连接一个信号再发出信号一个效果,都是Qt::QueuedConnection效果.
        QTimer::singleShot(0, myImage, SLOT(startImageCreate()));
    }

    return a.exec();
}

#include "main.moc"

你好,这段代码是只执行一次的显示,即一次1到9的打印,如果想反复打印的话,是不是需要把QTimer::singleShot(0, myImage, SLOT(startImageCreate()));放入一个定时器响应函数中呢?
大卫无限 2017-07-18
  • 打赏
  • 举报
回复

#include <QCoreApplication>
#include <QEventLoop>
#include <QSemaphore>
#include <QTimer>
#include <QThread>
#include <QDebug>

class MyImage : public QThread
{
    Q_OBJECT
public:
    explicit MyImage(QSemaphore *sem, int index = 0) : sem(sem), index(index){}
    ~MyImage() { this->exit(); this->wait(); }

public slots :
    void startImageCreate()
    {
        sem->acquire(index);
        qDebug() << "index:" << index;
        sem->release(index+1);

        this->exit();
    }

private:
    QSemaphore *sem;
    int index;
};

class Process1_9
{
public:
    Process1_9() : sem(1){}
    ~Process1_9(){}

    void process()
    {
        QEventLoop loop;

        QVector<MyImage*> threads;
        for (int k = 1; k <= 9; k++)
        {
            MyImage *myImage = new MyImage(&sem, k);
            if (k == 9)
            {
                QObject::connect(myImage, SIGNAL(finished()), &loop, SLOT(quit()));
            }

            threads.append(myImage);

            myImage->start();
            myImage->moveToThread(myImage);

            QTimer::singleShot(0, myImage, SLOT(startImageCreate()));
        }

        loop.exec();

        qDeleteAll(threads);
    }

private:
     QSemaphore sem;
};

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

    for (int i = 0; i < 3; ++i)
    {
        Process1_9 p;
        p.process();

        qDebug() << "===times:" << i + 1;
        QEventLoop loop;
        QTimer::singleShot(1000, &loop, SLOT(quit()));
        loop.exec();
    }

    return a.exec();
}

#include "main.moc"

就是把1-9的执行再封装一下呀. 方式很多,我随便写的.你看着修改吧.
大卫无限 2017-07-17
  • 打赏
  • 举报
回复
我给你发动了一下.相信应该可以理解. 没有使用锁,使用的信号量.它正好可以满足你的需求.


#include <QCoreApplication>
#include <QSemaphore>
#include <QTimer>
#include <QThread>
#include <QDebug>

class MyImage : public QObject
{
    Q_OBJECT
public:
    explicit MyImage(int index = 0);
public slots :
    void startImageCreate();
private:
    int index;
};
static QSemaphore sem(1);

MyImage::MyImage(int No) :QObject()
{
    index = No  ;
}

void MyImage::startImageCreate()
{
    sem.acquire(index); //获取资源,
    qDebug() << "index:" << index;
    sem.release(index+1);//释放多一个的资源,刚好可以,让下一个acquire获取成功.
}

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

    QVector<QThread*> threads;
    for (int k = 1; k <= 9; k++) //从一开始.到9结束
    {
        QThread *imageThread = new QThread;
        MyImage *myImage = new MyImage(k);

        imageThread->start(); //启动线程
        myImage->moveToThread(imageThread);

        threads.append(imageThread);

        //用QTimer来触发槽,和连接一个信号再发出信号一个效果,都是Qt::QueuedConnection效果.
        QTimer::singleShot(0, myImage, SLOT(startImageCreate()));
    }

    return a.exec();
}

#include "main.moc"

purplepare 2017-07-17
  • 打赏
  • 举报
回复
引用 1 楼 qqwangfan 的回复:
多线程没法按照你的要求依次调用,如何调用系统会有一个调度策略,按照线程优先级或者系统资源使用率等来调度线程,你所能做的是保证你的代码在多线程环境下运行不出错,使用互斥量是为了保证锁住的代码在同一时间只有一个线程运行,而不会是多个线程同时运行该段代码导致结果出错。
如果,这九个线程结束后,都会通过信号量-槽的方式调用主线程里的函数,也就是九个线程同时访问主线程里的响应函数,即使,我用vectro<int> vecTemp , 九个ID,分别存储数据到对应的vecTemp[ID]下,请问这种情况,我需要对主线程里的响应函数使用互斥量嘛?
  • 打赏
  • 举报
回复
多线程没法按照你的要求依次调用,如何调用系统会有一个调度策略,按照线程优先级或者系统资源使用率等来调度线程,你所能做的是保证你的代码在多线程环境下运行不出错,使用互斥量是为了保证锁住的代码在同一时间只有一个线程运行,而不会是多个线程同时运行该段代码导致结果出错。

16,203

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧