最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Qt中實(shí)現(xiàn)多線程導(dǎo)出數(shù)據(jù)功能的四種方式小結(jié)

 更新時(shí)間:2025年08月06日 16:11:43   作者:zbycode  
在以往的項(xiàng)目開發(fā)中,在很多地方用到了多線程,本文將記錄下在Qt開發(fā)中用到的多線程技術(shù)實(shí)現(xiàn)方法,以導(dǎo)出指定范圍的數(shù)字到txt文件為例,展示多線程不同的實(shí)現(xiàn)方式

前言

在以往的項(xiàng)目開發(fā)中,在很多地方用到了多線程。針對(duì)不同的業(yè)務(wù)邏輯,需要使用不同的多線程實(shí)現(xiàn)方法,來(lái)達(dá)到優(yōu)化項(xiàng)目的目的。本文記錄下在Qt開發(fā)中用到的多線程技術(shù)實(shí)現(xiàn)方法,以導(dǎo)出指定范圍的數(shù)字到txt文件為例,展示多線程不同的實(shí)現(xiàn)方式。

示例已上傳到gittee,地址:https://gitee.com/zbylalalala1/qt_-thread-demo.git

導(dǎo)出文件的示例工具類

首先提供一個(gè)工具類,用于將指定范圍的數(shù)字寫入txt文件。

#ifndef UTILITIES_H
#define UTILITIES_H

#include <QString>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QDir>
#include <QDebug>
class Utilities
{
public:
    static bool writeNumbersToFile(int start, int end, const QString& prefix = "numbers")
    {
        if (start > end) {
            qDebug() << "起始數(shù)字不能大于結(jié)束數(shù)字";
            return false;
        }
        
        // 獲取當(dāng)前時(shí)間并格式化為文件名
        QDateTime currentTime = QDateTime::currentDateTime();
        QString timeString = currentTime.toString("yyyy-MM-dd_hh-mm-ss");
        QString fileName = QString("%1_%2_to_%3_%4.txt")
                          .arg(prefix)
                          .arg(start)
                          .arg(end)
                          .arg(timeString);
        
        // 創(chuàng)建文件對(duì)象
        QFile file(fileName);
        
        // 以寫入模式打開文件
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            qDebug() << "無(wú)法創(chuàng)建文件:" << fileName;
            return false;
        }
        
        // 創(chuàng)建文本流
        QTextStream out(&file);
        
        // 寫入指定范圍的數(shù)字
        int count = 0;
        for (int i = start; i <= end; ++i) {
            out << i;
            count++;
            
            // 每10個(gè)數(shù)字換行
            if (count % 10 == 0 || i == end) {
                out << "\n";
            } else {
                out << " "; // 數(shù)字之間用空格分隔
            }
        }
        
        // 關(guān)閉文件
        file.close();
        
        qDebug() << "成功寫入文件:" << fileName;
        qDebug() << "文件路徑:" << QDir::currentPath() + "/" + fileName;
        qDebug() << "寫入數(shù)字范圍:" << start << "到" << end << ",共" << (end - start + 1) << "個(gè)數(shù)字";
        
        return true;
    }
    
    // 獲取當(dāng)前工作目錄
    static QString getCurrentPath()
    {
        return QDir::currentPath();
    }
    
    // 檢查文件是否存在
    static bool fileExists(const QString& fileName)
    {
        QFile file(fileName);
        return file.exists();
    }
};

#endif // UTILITIES_H

QThread

使用QThread類來(lái)創(chuàng)建線程,是Qt中最簡(jiǎn)單的一種多線程實(shí)現(xiàn)方式,不過(guò)一般不建議使用,因?yàn)樗墓δ鼙容^有限。

使用QThread的方式為:繼承QThread并重寫run()函數(shù)。

ExportThread.h 

#ifndef EXPORTTHREAD_H
#define EXPORTTHREAD_H

#include <QThread>
#include <QDebug>
#include "Utilities.h"

class ExportThread : public QThread
{
    Q_OBJECT

public:
    explicit ExportThread(QObject *parent = nullptr);
    
    // 設(shè)置導(dǎo)出參數(shù)
    void setExportParams(int start = 1, int end = 10000, const QString& prefix = "numbers");
    
protected:
    void run() override;
    
signals:
    void exportStarted();
    void exportFinished(bool success, const QString& message);
    void progressUpdate(int current, int total);
    
private:
    int m_start;
    int m_end;
    QString m_prefix;
};

#endif // EXPORTTHREAD_H

ExportThread.cpp

#include "ExportThread.h"
#include <QDateTime>
#include <QDir>

ExportThread::ExportThread(QObject *parent)
    : QThread(parent)
    , m_start(1)
    , m_end(10000)
    , m_prefix("numbers")
{
}

void ExportThread::setExportParams(int start, int end, const QString& prefix)
{
    m_start = start;
    m_end = end;
    m_prefix = prefix;
}

void ExportThread::run()
{
    qDebug() << "導(dǎo)出線程開始運(yùn)行...";
    emit exportStarted();
    
    try {
        bool success = Utilities::writeNumbersToFile(m_start, m_end, m_prefix);
        if (success) {
            emit exportFinished(true, QString("文件導(dǎo)出成功!范圍:%1-%2").arg(m_start).arg(m_end));
        } else {
            emit exportFinished(false, "文件導(dǎo)出失敗!");
        }
        qDebug() << "導(dǎo)出線程完成";
        
    } catch (const std::exception& e) {
        qDebug() << "導(dǎo)出過(guò)程中發(fā)生異常:" << e.what();
        emit exportFinished(false, QString("導(dǎo)出過(guò)程中發(fā)生異常: %1").arg(e.what()));
    }
}

使用方式:

ExportThread *exportThread = new ExportThread(this);
exportThread->setExportParams(1, 10000, "numbers");
exportThread->start();

QObject的moveToThread方法實(shí)現(xiàn)多線程

QObject的moveToThread方法可以將一個(gè)QObject對(duì)象移動(dòng)到指定的線程中,實(shí)現(xiàn)多線程。

使用方式:

QObject *obj = new QObject();
QThread *thread = new QThread();
obj->moveToThread(thread);
thread->start();

示例:

FileExportWorker.h 

#ifndef FILEEXPORTWORKER_H
#define FILEEXPORTWORKER_H

#include <QObject>
#include "Utilities.h"

class FileExportWorker : public QObject
{
    Q_OBJECT
public:
    explicit FileExportWorker(QObject *parent = nullptr);
    void exportNumbers(int start, int end, const QString& prefix);

signals:
    void progressUpdated(int current, int total);
    void statusUpdated(const QString& status);

public slots:
};

#endif // FILEEXPORTWORKER_H

FileExportWorker.cpp

#include "FileExportWorker.h"
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QDir>
#include <QDebug>
#include <QThread>
#include <QCoreApplication>

FileExportWorker::FileExportWorker(QObject *parent)
    : QObject(parent)
    , m_start(1)
    , m_end(10000)
    , m_prefix("numbers")
    , m_shouldStop(false)
{
}

void FileExportWorker::setExportParams(int start, int end, const QString& prefix)
{
    m_start = start;
    m_end = end;
    m_prefix = prefix;
}

void FileExportWorker::doExport()
{
    qDebug() << "Worker線程ID:" << QThread::currentThreadId();
    qDebug() << "開始導(dǎo)出任務(wù)...";
    
    m_shouldStop = false;
    emit exportStarted();
    emit statusUpdated("正在準(zhǔn)備導(dǎo)出...");
    
    try {
        bool success = false;
        
        emit statusUpdated("使用自定義參數(shù)導(dǎo)出...");
        success = exportNumbersWithProgress();
        
        if (m_shouldStop) {
            emit exportFinished(false, "導(dǎo)出已被用戶取消");
        } else if (success) {
            emit exportFinished(true, QString("文件導(dǎo)出成功!范圍:%1-%2").arg(m_start).arg(m_end));
        } else {
            emit exportFinished(false, "文件導(dǎo)出失??!");
        }
        
    } catch (const std::exception& e) {
        qDebug() << "導(dǎo)出過(guò)程中發(fā)生異常:" << e.what();
        emit exportFinished(false, QString("導(dǎo)出過(guò)程中發(fā)生異常: %1").arg(e.what()));
    }
    
    qDebug() << "導(dǎo)出任務(wù)完成";
}

void FileExportWorker::stopExport()
{
    m_shouldStop = true;
    emit statusUpdated("正在停止導(dǎo)出...");
}

bool FileExportWorker::exportNumbersWithProgress()
{
    // 獲取當(dāng)前時(shí)間并格式化為文件名
    QDateTime currentTime = QDateTime::currentDateTime();
    QString timeString = currentTime.toString("yyyy-MM-dd_hh-mm-ss");
    QString fileName = QString("%1_%2_to_%3_%4.txt")
                      .arg(m_prefix)
                      .arg(m_start)
                      .arg(m_end)
                      .arg(timeString);
    
    // 創(chuàng)建文件對(duì)象
    QFile file(fileName);
    
    // 以寫入模式打開文件
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "無(wú)法創(chuàng)建文件:" << fileName;
        return false;
    }
    
    // 創(chuàng)建文本流
    QTextStream out(&file);
    
    int total = m_end - m_start + 1;
    int count = 0;
    
    // 寫入指定范圍的數(shù)字
    for (int i = m_start; i <= m_end; ++i) {
        if (m_shouldStop) {
            file.close();
            QFile::remove(fileName); // 刪除未完成的文件
            return false;
        }
        
        out << i;
        count++;
        
        // 每10個(gè)數(shù)字換行
        if (count % 10 == 0 || i == m_end) {
            out << "\n";
        } else {
            out << " "; // 數(shù)字之間用空格分隔
        }
        
        // 每處理100個(gè)數(shù)字發(fā)送一次進(jìn)度更新
        if (count % 100 == 0 || i == m_end) {
            emit progressUpdated(count, total);
            emit statusUpdated(QString("已處理 %1/%2 個(gè)數(shù)字").arg(count).arg(total));
            // 讓出CPU時(shí)間,允許其他操作
            QCoreApplication::processEvents();
        }
    }
    
    // 關(guān)閉文件
    file.close();
    
    qDebug() << "成功寫入文件:" << fileName;
    qDebug() << "文件路徑:" << QDir::currentPath() + "/" + fileName;
    qDebug() << "寫入數(shù)字范圍:" << m_start << "到" << m_end << ",共" << total << "個(gè)數(shù)字";
    
    return true;
}

QConcurrent實(shí)現(xiàn)多線程導(dǎo)出數(shù)據(jù)

QConcurrent是Qt提供的一個(gè)并發(fā)編程框架,用于簡(jiǎn)化多線程編程。它提供了一些方便的函數(shù)和類,用于在多個(gè)線程中執(zhí)行任務(wù)。本示例通過(guò)QConcurrent實(shí)現(xiàn)導(dǎo)出任務(wù),實(shí)現(xiàn)多線程導(dǎo)出數(shù)據(jù)。

使用方式:

QFuture<bool> future = QConcurrent::run(this, &FileExportWorker::exportNumbersWithProgress);

示例:

FileExportWorker.h 

#ifndef CONCURRENTEXPORTER_H
#define CONCURRENTEXPORTER_H

#include <QObject>
#include <QString>
#include <QFuture>
#include <QFutureWatcher>
#include <QtConcurrent>
#include "Utilities.h"

class ConcurrentExporter : public QObject
{
    Q_OBJECT

public:
    explicit ConcurrentExporter(QObject *parent = nullptr);
    
    // 開始導(dǎo)出任務(wù)
    void startExport(int start = 1, int end = 10000, const QString& prefix = "concurrent");
    
    // 取消導(dǎo)出任務(wù)
    void cancelExport();
    
    // 檢查是否正在運(yùn)行
    bool isRunning() const;

signals:
    void exportStarted();
    void exportFinished(bool success, const QString& message);

private slots:
    void onExportFinished();

private:
    QFutureWatcher<bool> *m_watcher;
    QFuture<bool> m_future;
    int m_start;
    int m_end;
    QString m_prefix;
};

#endif // CONCURRENTEXPORTER_H

FileExportWorker.cpp

#include "ConcurrentExporter.h"
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QDir>
#include <QDebug>
#include <QThread>
#include <QCoreApplication>
#include <QtConcurrent/QtConcurrentRun>

ConcurrentExporter::ConcurrentExporter(QObject *parent)
    : QObject(parent)
    , m_watcher(new QFutureWatcher<bool>(this))
    , m_start(1)
    , m_end(10000)
    , m_prefix("concurrent")
{
    // 連接QFutureWatcher的信號(hào)
    connect(m_watcher, &QFutureWatcher<bool>::finished, this, &ConcurrentExporter::onExportFinished);
}

void ConcurrentExporter::startExport(int start, int end, const QString& prefix)
{
    if (isRunning()) {
        qDebug() << "導(dǎo)出任務(wù)已在運(yùn)行中";
        return;
    }
    
    m_start = start;
    m_end = end;
    m_prefix = prefix;
    
    qDebug() << "使用Qt Concurrent開始導(dǎo)出任務(wù)...";
    qDebug() << "當(dāng)前線程ID:" << QThread::currentThreadId();
    
    emit exportStarted();
    
    m_future = QtConcurrent::run([=]() {
        qDebug() << "工作線程ID:" << QThread::currentThreadId();
        return Utilities::writeNumbersToFile(start, end, prefix);
    });
    // 設(shè)置QFutureWatcher監(jiān)視QFuture
    m_watcher->setFuture(m_future);
}

void ConcurrentExporter::cancelExport()
{
    if (isRunning()) {
        m_future.cancel();
    }
}

bool ConcurrentExporter::isRunning() const
{
    return m_future.isRunning();
}

void ConcurrentExporter::onExportFinished()
{
    bool success = false;
    QString message;
    
    if (m_future.isCanceled()) {
        message = "導(dǎo)出任務(wù)已被取消";
    } else {
        try {
            success = m_future.result();
            if (success) {
                message = QString("文件導(dǎo)出成功!范圍:%1-%2").arg(m_start).arg(m_end);
            } else {
                message = "文件導(dǎo)出失??!";
            }
        } catch (const std::exception& e) {
            message = QString("導(dǎo)出過(guò)程中發(fā)生異常: %1").arg(e.what());
        }
    }
    
    emit exportFinished(success, message);
    qDebug() << "Qt Concurrent導(dǎo)出任務(wù)完成:" << message;
}

QRunnable結(jié)合QThreadPool方法實(shí)現(xiàn)多線程導(dǎo)出數(shù)據(jù)

QRunnable是Qt提供的一個(gè)接口,用于在多線程中執(zhí)行任務(wù)。QThreadPool是一個(gè)線程池,用于管理多個(gè)線程。本示例通過(guò)QRunnable接口實(shí)現(xiàn)導(dǎo)出任務(wù),通過(guò)QThreadPool線程池管理線程,實(shí)現(xiàn)多線程導(dǎo)出數(shù)據(jù)。

使用方式:

QThreadPool *pool = QThreadPool::globalInstance();
RunnableExportTask *task = new RunnableExportTask(1, 10000, "numbers");
pool->start(task);

示例:

RunnableExportTask.h

#ifndef RUNNABLEEXPORTTASK_H
#define RUNNABLEEXPORTTASK_H

#include <QRunnable>
#include <QObject>
#include <QString>
#include <QDebug>
#include "Utilities.h"

// 由于QRunnable不繼承QObject,我們需要一個(gè)信號(hào)發(fā)射器
class ExportTaskNotifier : public QObject
{
    Q_OBJECT

public:
    explicit ExportTaskNotifier(QObject *parent = nullptr) : QObject(parent) {}
    
    void emitStarted() { emit exportStarted(); }
    void emitFinished(bool success, const QString& message) { emit exportFinished(success, message); }
    void emitProgress(const QString& status) { emit progressUpdated(status); }

signals:
    void exportStarted();
    void exportFinished(bool success, const QString& message);
    void progressUpdated(const QString& status);
};

class RunnableExportTask : public QRunnable
{
public:
    explicit RunnableExportTask(int start = 1, int end = 10000, const QString& prefix = "runnable");
    
    // 設(shè)置通知器,用于發(fā)送信號(hào)
    void setNotifier(ExportTaskNotifier *notifier);
    
    // 設(shè)置導(dǎo)出參數(shù)
    void setExportParams(int start, int end, const QString& prefix);
    
    // QRunnable接口實(shí)現(xiàn)
    void run() override;
    
private:
    int m_start;
    int m_end;
    QString m_prefix;
    ExportTaskNotifier *m_notifier;
};

#endif // RUNNABLEEXPORTTASK_H

RunnableExportTask.cpp

#include "RunnableExportTask.h"
#include <QThread>
#include <QDebug>

RunnableExportTask::RunnableExportTask(int start, int end, const QString& prefix)
    : m_start(start)
    , m_end(end)
    , m_prefix(prefix)
    , m_notifier(nullptr)
{
    // 設(shè)置任務(wù)完成后自動(dòng)刪除
    setAutoDelete(true);
}

void RunnableExportTask::setNotifier(ExportTaskNotifier *notifier)
{
    m_notifier = notifier;
}

void RunnableExportTask::setExportParams(int start, int end, const QString& prefix)
{
    m_start = start;
    m_end = end;
    m_prefix = prefix;
}

void RunnableExportTask::run()
{
    qDebug() << "QRunnable任務(wù)開始運(yùn)行...";
    qDebug() << "當(dāng)前線程ID:" << QThread::currentThreadId();
    
    if (m_notifier) {
        m_notifier->emitStarted();
        m_notifier->emitProgress("QRunnable任務(wù):正在準(zhǔn)備導(dǎo)出...");
    }
    
    try {
        if (m_notifier) {
            m_notifier->emitProgress("QRunnable任務(wù):開始寫入文件...");
        }
        
        bool success = Utilities::writeNumbersToFile(m_start, m_end, m_prefix);
        
        if (success) {
            QString message = QString("文件導(dǎo)出成功!范圍:%1-%2").arg(m_start).arg(m_end);
            if (m_notifier) {
                m_notifier->emitProgress("QRunnable任務(wù):導(dǎo)出完成");
                m_notifier->emitFinished(true, message);
            }
            qDebug() << "QRunnable任務(wù)完成:" << message;
        } else {
            QString message = "文件導(dǎo)出失?。?;
            if (m_notifier) {
                m_notifier->emitFinished(false, message);
            }
            qDebug() << "QRunnable任務(wù)失敗:" << message;
        }
        
    } catch (const std::exception& e) {
        QString message = QString("導(dǎo)出過(guò)程中發(fā)生異常: %1").arg(e.what());
        qDebug() << "QRunnable任務(wù)異常:" << message;
        if (m_notifier) {
            m_notifier->emitFinished(false, message);
        }
    }
    
    qDebug() << "QRunnable任務(wù)結(jié)束";
}

到此這篇關(guān)于Qt中實(shí)現(xiàn)多線程導(dǎo)出數(shù)據(jù)功能的四種方式小結(jié)的文章就介紹到這了,更多相關(guān)Qt多線程導(dǎo)出數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解C++編程中的文件流與字符串流

    詳解C++編程中的文件流與字符串流

    這篇文章主要介紹了C++編程中的文件流與字符串流,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • C語(yǔ)言中數(shù)組排序淺析

    C語(yǔ)言中數(shù)組排序淺析

    這篇文章主要為大家介紹了C語(yǔ)言算法練習(xí)中數(shù)組元素排序的四種類型,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語(yǔ)言有一定幫助,需要的可以參考一下
    2022-12-12
  • c/c++中變量的聲明和定義深入解析

    c/c++中變量的聲明和定義深入解析

    “聲明”為編譯服務(wù),用于類型檢查 ;“定義”在運(yùn)行時(shí)會(huì)分配空間,不能重復(fù)定義,同時(shí)具備聲明的功能
    2013-09-09
  • C/C++中使用列表框組件Qt?ListWidget

    C/C++中使用列表框組件Qt?ListWidget

    本文詳細(xì)講解了C/C++中使用列表框組件Qt?ListWidget的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-11-11
  • C++中關(guān)于互斥量的全面認(rèn)知

    C++中關(guān)于互斥量的全面認(rèn)知

    線程的主要優(yōu)勢(shì)在于,能夠通過(guò)全局變量來(lái)共享信息。不過(guò),這種便捷的共享是有代價(jià)的:必須確保多個(gè)線程不會(huì)同時(shí)修改同一變量,或者某一線程不會(huì)讀取正由其他線程修改的變量。為了防止出現(xiàn)線程某甲試圖訪?問(wèn)一共享變量時(shí),線程某乙正在對(duì)其進(jìn)行修改。引入了互斥量
    2022-05-05
  • 簡(jiǎn)單掌握桶排序算法及C++版的代碼實(shí)現(xiàn)

    簡(jiǎn)單掌握桶排序算法及C++版的代碼實(shí)現(xiàn)

    桶排序是將要排序的算法按桶分組排序之后再遍歷匯總的一種線性排序算法,下面就讓我們來(lái)通過(guò)小例子簡(jiǎn)單掌握桶排序算法及C++版的代碼實(shí)現(xiàn)^^
    2016-07-07
  • VC++實(shí)現(xiàn)View內(nèi)容保存為圖片的方法

    VC++實(shí)現(xiàn)View內(nèi)容保存為圖片的方法

    這篇文章主要介紹了VC++實(shí)現(xiàn)View內(nèi)容保存為圖片的方法,涉及VC++中Bitmap類的save方法相關(guān)使用技巧,需要的朋友可以參考下
    2016-08-08
  • C語(yǔ)言超詳細(xì)i講解雙向鏈表

    C語(yǔ)言超詳細(xì)i講解雙向鏈表

    在實(shí)際生活中,我們用到的最多的兩種鏈表結(jié)構(gòu)就是單鏈表和雙向帶頭鏈表,上一篇已經(jīng)介紹了單鏈表的實(shí)現(xiàn)以及一些應(yīng)用,接下來(lái)我為大家詳細(xì)介紹一下雙向鏈表,以及一些鏈表oj題
    2022-05-05
  • C語(yǔ)言內(nèi)存操作函數(shù)使用示例梳理講解

    C語(yǔ)言內(nèi)存操作函數(shù)使用示例梳理講解

    這篇文章主要介紹了C語(yǔ)言庫(kù)函數(shù)中的內(nèi)存操作函數(shù)memcpy()、memmove()、memset()、memcmp()使用示例分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-09-09
  • C++大數(shù)模板(推薦)

    C++大數(shù)模板(推薦)

    本篇文章是對(duì)C++大數(shù)模板的程序代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評(píng)論

伊川县| 揭东县| 大英县| 布尔津县| 禹城市| 壤塘县| 门源| 南汇区| 五指山市| 奇台县| 汪清县| 苗栗市| 阿拉善右旗| 祥云县| 彭阳县| 洛川县| 东乡族自治县| 鄂托克旗| 永嘉县| 朝阳区| 崇文区| 吉隆县| 五指山市| 广饶县| 霍邱县| 明溪县| 绥芬河市| 江山市| 抚松县| 镇平县| 江阴市| 汕尾市| 南安市| 临城县| 新密市| 邳州市| 武汉市| 武清区| 永城市| 米易县| 金华市|