国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Qt多線程使用的兩種方式

這篇具有很好參考價值的文章主要介紹了Qt多線程使用的兩種方式。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、Qt多線程兩種方式:

方式1:繼承自QThread類,重載run函數(shù)。此實現(xiàn)方法只有run()函數(shù)內(nèi)的代碼是運行在子線程內(nèi)。(不使用事件循環(huán))

使用方法
(1)run函數(shù)內(nèi)有一個while或for的死循環(huán)(模擬耗時操作);

(2)通過一個標記位來控制死循環(huán)的退出;

(3)run()函數(shù)中無限循環(huán)記得強制休息,如果不加就會造成運行后CPU占用率100%的問題。一定要運行sleep將時間片讓出去一下,處理其他事物;

(4)run()對于線程的作用相當于main函數(shù)對于應用程序。它是線程的入口,run的開始和結(jié)束意味著線程的開始和結(jié)束;

(5)在調(diào)用start()之后,新創(chuàng)建的線程就會調(diào)用run函數(shù),默認實現(xiàn)調(diào)用exec()。

使用場景
適用于后臺執(zhí)行長時間的耗時操作,如文件復制、網(wǎng)絡(luò)數(shù)據(jù)讀取。

代碼示例:

#ifndef QDEMOTHREAD_H
#define QDEMOTHREAD_H

#include <QThread>
#include <QDebug>

class QDemoThread : public QThread
{
    Q_OBJECT

public:
    QDemoThread(QObject* parent = nullptr);
    ~QDemoThread();

protected:
    void run() override;

public:
    void stop();

private:
    bool flag;
};
#endif // QDEMOTHREAD_H

#include "qdemothread.h"

QDemoThread::QDemoThread(QObject* parent) : QThread(parent)
{

}

QDemoThread::~QDemoThread()
{

}

void QDemoThread::run()
{
    flag = true;
    while(flag)
    {
        qDebug() << "thread id:" << QThread::currentThreadId();
        sleep(1);       //此處必須強制休息,否則CPU占用率很大
    }
}

void QDemoThread::stop()
{
    flag = false;
    if(isRunning())
    {
        exit();  // 結(jié)束線程
        wait();  // 等待退出
    }
}

方式二(推薦):
創(chuàng)建一個QThread和QWorker(繼承自QObject)類對象,使用moveToThread函數(shù)移動到thread中運行,通過thread類start信號和worker的init槽函數(shù)綁定,init槽函數(shù)內(nèi)是一些初始化操作,然后定義個定時器,周期觸發(fā)doWork()。(使用事件循環(huán))

使用信號和槽時根本不用考慮多線程的存在。也不用使用QMutex來進行同步,Qt的事件循環(huán)會自己自動處理好這個。

網(wǎng)上有很多教程是在doWork()中使用while(isRunning)死循環(huán)的形式,不建議這么干,如果線程一直在doWork中死循環(huán),那么他是無法接收到來自外部的信號的。推薦的方法是用定時器周期觸發(fā)。

使用場景:
適用于事務(wù)性操作,如文件讀寫、數(shù)據(jù)庫讀寫。

適合單次任務(wù)執(zhí)行,即有點像懶人,觸發(fā)一下,干一次活;

適合干完活,需要主動推送一個通知;

適合用于簡化多線程中,對數(shù)據(jù)安全的保護。

不適用高頻率任務(wù),即跑完一個任務(wù),可能沒有時間休息,持續(xù)跑。

執(zhí)行高頻率任務(wù),還是需要使用重寫QThread::run()的方式,來實現(xiàn)。

代碼示例:

QWorker類:

#ifndef QWORKER_H
#define QWORKER_H

#include <QObject>
#include <QThread>
#include <QDebug>

class QWorker : public QObject
{
    Q_OBJECT
public:
    explicit QWorker(QObject *parent = nullptr);
    ~QWorker();

signals:
    void newData(QByteArray data);    // 將本類內(nèi)的私有數(shù)據(jù)通過該信號發(fā)射出去,供外部使用

public slots:
    void init();         // 一些必要的初始化操作寫在此函數(shù)內(nèi)
    void doWork();       // 一些耗時操作寫在此函數(shù)內(nèi)
    void writeData(const char* buf, qint64 len);  // 供外部使用的操作接口
};

#endif // QWORKER_H
#include "qworker.h"

QWorker::QWorker(QObject *parent) : QObject(parent)
{
    qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId();
}

QWorker::~QWorker()
{
    qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId();
}

void QWorker::init()
{
    qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId();
}

void QWorker::doWork()
{
    static int count = 0;
    qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId() << ">>>" << count++;
}

void QWorker::writeData(const char* buf, qint64 len)
{
    qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId() << ">>>" << QByteArray(buf, len);
}

主線程:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "qworker.h"
#include <QTimer>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
    QWorker* worker;
    QThread* thread;
    QTimer* timer;

signals:
    void writeData(const char* buf, qint64 len);
    void stopWork();
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId();

    timer = new QTimer(this);

    thread = new QThread();  // 不要指定parent
    worker = new QWorker();  // 不要指定parent

	// thread的finished和deleteLater相連接后,在thread退出時自動刪除thread對象,無需手動delete thread
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 
    // thread的finished和worker的deleteLater相連接后,在thread退出時自動刪除worker對象,無需手動delete worker
    connect(thread, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(started()), worker, SLOT(init()));

    connect(timer, SIGNAL(timeout()), worker, SLOT(doWork()));

    connect(this, SIGNAL(writeData(const char*,qint64)), worker, SLOT(writeData(const char*,qint64)));

    worker->moveToThread(thread);

    thread->start();

    timer->start(1000);  // 1000ms執(zhí)行一次doWork()
}

MainWindow::~MainWindow()
{
    if(timer->isActive())
    {
        timer->stop();
    }

    if(thread->isRunning())
    {
        thread->quit();
        thread->wait();
    }

    qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId();

    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    emit writeData("hello world\r\n", 13);
}

二、QT線程同步

線程同步:Qt中使用多線程時候,多線程的同步就是一個不可避免的問題。

多線程的同步就是使多個線程在同時執(zhí)行同一段代碼的時候,有順序的執(zhí)行,不會出現(xiàn)同時有兩個或者多個線程執(zhí)行同一段代碼的情況,特別是在對變量或者文件執(zhí)行寫操作的時候。也就是所謂的線程安全,線程安全指的是這段代碼在一個線程或者多個線程執(zhí)行的過程中,不加同步機制或者任何其他代碼,執(zhí)行的結(jié)果是一樣的,這就是線程安全。

在Qt中常用的同步方法是使用鎖機制,但是如果使用的方法不對或者時機不對同樣也不會起到線程同步的效果。

例如: 有兩個進程都對一個變量進行讀寫操作,這時就需要互斥量來進行線程同步,這個互斥量必須是全局的,不然如果各自在.cpp中聲明一個QMutex mutex;是沒有任何意義的。因為:每個線程對象都創(chuàng)建了一個QMutex對象,兩個線程在運行過程中各自執(zhí)行的是自己的鎖,所以每個鎖有且只有一個線程在執(zhí)行。它們是互不干擾的,所有雖然加鎖了,也沒有起到同步的作用。

代碼示例:

主程序:

// 多線程方式1
myThread = new MyThread();    // 繼承自QThread
myThread->start();

// 多線程方式2
myThread1 = new MyThread1();    // 繼承自QObject
thread1 = new QThread();
connect(thread1, SIGNAL(started(), myThread1 , SLOT(doWork)));
myThread1->moveToThread(thread1 );
thread1->start();

線程1:MyThread.cpp

#include "mythread.h"
#include <QMutex>

QMutex mutex;
extern int globalCount ;

MyThread::MyThread()
{
    isStop = true;
}

void MyThread::closeThread()
{
    isStop = true;
}
//重寫基類的run函數(shù)
void MyThread::run()//只有run()里面在新的線程里
{
    qDebug()<<tr("mythread QThread::currentThreadId()==")<<QThread::currentThreadId();
    isStop = false;

//這種方式還是相當于在主線程里面執(zhí)行
//    timer= new QTimer(NULL);
//    connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
//    timer->start(1000);
//    this->exec();
    while(1)
    {
        if(isStop)
        {
            return;
        }

        QMutexLocker locker(&mutex);
        qDebug()<<"globalCount: " << ++globalCount <<QThread::currentThreadId();

        sleep(5);//QThread
    }
}

//這種方式還是相當于在主線程里面執(zhí)行
void MyThread::onTimeout()
{
    qDebug()<<tr("mythread QThread::currentThreadId()==")<<QThread::currentThreadId();
    qDebug()<<"globalCount: " << ++globalCount;
}

線程2:MyThread1.cpp文章來源地址http://www.zghlxwxcb.cn/news/detail-409226.html

#include "mythread1.h"
#include <QMutex>

extern QMutex mutex;
QMutex mutex1;
extern int globalCount ;

MyThread1::MyThread1(QObject *parent) : QObject(parent)
{
    isStop = true;
}

void MyThread1::closeThread()
{
    isStop = true;
}

void MyThread1::doWork()
{
    qDebug()<<tr("mythread2 QThread::currentThreadId()==")<<QThread::currentThreadId();
    isStop = false;

    //定時方式1:(都是在子線程中)
    timer= new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
    timer->start(1000);

    //定時方式2:(都是在子線程中)
//    while(1)
//    {
//        if(isStop)
//        {
//            return;
//        }

//        QMutexLocker locker(&mutex);
//        qDebug()<<"globalCount: " << ++globalCount <<QThread::currentThreadId();

//        Sleep(1000);//<windows.h>,大寫的S,單位是微秒
//    }
}

void MyThread1::onTimeout()
{
    QMutexLocker locker(&mutex);
    qDebug()<<"globalCount: " << ++globalCount <<QThread::currentThreadId();

}

到了這里,關(guān)于Qt多線程使用的兩種方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • QT打包的兩種方式

    QT打包的兩種方式

    QT打包的兩種方式: 一個是QT5自帶的windeployqt(不需要下載安裝),它可以找到程序(exe)用到的所有庫文件,并且都拷貝到exe程序的當前文件。此時打包的exe較小,需要和拷貝進來的文件放一起運行,也可以將這些文件再次打包成一個大的exe文件,此時用的第二種打包方式

    2024年02月16日
    瀏覽(26)
  • 線程方法接收參數(shù)示例,Java的兩種線程實現(xiàn)方式區(qū)別

    總所周知,Java實現(xiàn)多線程有兩種方式,分別是繼承Thread類和實現(xiàn)Runable接口,那么它們的區(qū)別是什么? 繼承 Thread 類: 通過繼承 Thread 類,你可以創(chuàng)建一個直接表示線程的類。你可以覆蓋 Thread 類中的 run 方法來定義線程的邏輯。當調(diào)用 start 方法啟動線程時,會執(zhí)行該類中的

    2024年02月11日
    瀏覽(53)
  • 線程方法接收參數(shù)和返回參數(shù),Java的兩種線程實現(xiàn)方式對比

    總所周知,Java實現(xiàn)多線程有兩種方式,分別是繼承Thread類和實現(xiàn)Runable接口,那么它們的區(qū)別是什么? 繼承 Thread 類: 通過繼承 Thread 類,你可以創(chuàng)建一個直接表示線程的類。你可以覆蓋 Thread 類中的 run 方法來定義線程的邏輯。當調(diào)用 start 方法啟動線程時,會執(zhí)行該類中的

    2024年02月11日
    瀏覽(29)
  • 【Qt】QThread & moveTothread-多線程的兩種實現(xiàn)方法

    【Qt】QThread & moveTothread-多線程的兩種實現(xiàn)方法

    一、如何理解多線程 二、實現(xiàn)多線程的兩種方式(面向應用) 2.1 繼承 QThread 的類 2.2 (推薦這種方式)函數(shù) moveTothread() 三、多線程的釋放問題(善后工作) 類似我們單片機的編程,如在 Keil5 中對 51 單片機或者 STM32 單片機進行編程時,如果我們使用模塊化編程,那么 main.c 文

    2024年02月01日
    瀏覽(18)
  • 【linux 多線程并發(fā)】線程本地數(shù)據(jù)存儲的兩種方式,每個線程可以有同名全局私有數(shù)據(jù),以及兩種方式的性能分析

    ? 專欄內(nèi)容 : 參天引擎內(nèi)核架構(gòu) 本專欄一起來聊聊參天引擎內(nèi)核架構(gòu),以及如何實現(xiàn)多機的數(shù)據(jù)庫節(jié)點的多讀多寫,與傳統(tǒng)主備,MPP的區(qū)別,技術(shù)難點的分析,數(shù)據(jù)元數(shù)據(jù)同步,多主節(jié)點的情況下對故障容災的支持。 手寫數(shù)據(jù)庫toadb 本專欄主要介紹如何從零開發(fā),開發(fā)的

    2024年02月03日
    瀏覽(27)
  • Qt 測量文字展示尺寸的兩種方式

    比如我想求字符串中最大的字符寬度,這個時候?qū)γ總€字符的寬度求值肯定不是固定的,所以可以先用 MAXFLOAT 做約束,自適應寬度,代碼如下: 某些情況下我想做文字的自動折行,指定了文本展示框的寬度之后,高度要通過折行策略達到自適應的效果:

    2024年02月06日
    瀏覽(28)
  • Qt中實現(xiàn)頁面切換的兩種方式

    Qt中實現(xiàn)頁面切換的兩種方式

    在Qt中,可以使用QStackedWidget來實現(xiàn)兩個UI界面的互相轉(zhuǎn)換。QStackedWidget是一個堆疊窗口小部件,可以在其中添加多個子窗口,并且只顯示其中一個子窗口。 注意:QStackedWidget只能用來裝widget,不能裝mainwindow?。?! 注意: 上面這種想法是錯的! 下面這種想法才是對的! 注意

    2024年02月08日
    瀏覽(21)
  • QT操作excel的兩種方式 QT基礎(chǔ)入門【Excel的操作】

    QT操作excel的方式有兩種:QAxObject 和QtXlsx QAxObject是通過調(diào)用office或者wps組件來實現(xiàn)對excel圖表的操作的。只有裝office軟件或者wps軟件就可以實現(xiàn),但是 如果只裝了office軟件,有時可以用有時不可以用; 如果只裝wps軟件,完全不能使用; 如果兩個都裝了,基本上結(jié)果不可控;

    2024年02月12日
    瀏覽(28)
  • Qt Http請求,post和get的兩種方式

    Qt Http請求,post和get的兩種方式

    今天我們介紹一下QT的http請求,這里有post和get兩種方式 一、post請求方式:參數(shù)分為網(wǎng)址和具體請求值兩個部分,有時候還需要設(shè)置頭信息,看具體情況定 二、get請求方式:參數(shù)和網(wǎng)址拼接到一起請求 三、主要區(qū)別: get用于請求獲取數(shù)據(jù),post向指定的資源創(chuàng)建修改數(shù)據(jù) g

    2024年02月15日
    瀏覽(26)
  • Springboot使用kafka的兩種方式

    在Spring Boot中使用Apache Kafka主要有兩種方式:使用Spring Kafka項目和使用Spring Boot的spring-boot-starter-kafka。以下是這兩種方式的簡要概述: 使用Spring Kafka項目 Spring Kafka是Spring官方提供的一個用于Apache Kafka的集成庫。雖然它不是一個Spring Boot專用的庫,但它可以與Spring Boot很好地集

    2024年02月20日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包