QT-多线程知识(例子:多线程下载小说)

来源:互联网 发布:卷积网络 pooling 编辑:程序博客网 时间:2024/05/29 05:55

一、新建一个线程类

继承QThread的一个线程类,实现run方法,同时要包含头文件

#include <QThread>

获取当前的线程id

currentThreadId()

线程睡眠(1秒)

sleep(1) 或msleep(1000) 或msleep(1000000)

线程优先级

setPriority()

线程让道

yieldCurrentThread()

线程终止

terminate()

线程开启

start()

线程等待

wait()

二、线程互斥

QMutex mt,通过lock与unlock来控制

QMutexLocker locker(&mt) 

// 生产者消费者模式,即信号模式

QSemaphore freeBytes(80);
QSemaphore usedBytes(0);

// 利用等待和唤醒来控制

三、多线程下载小说

1、mainwindow文件

#ifndef MAINWINDOW_H#define MAINWINDOW_H#pragma execution_character_set("utf-8")#include <QMainWindow>#include <QFileDialog>#include <QMessageBox>#include <QtNetwork>#include <QRegExp>#include "leaderthread.h"namespace Ui {class MainWindow;}class MainWindow : public QMainWindow{    Q_OBJECTpublic:    explicit MainWindow(QWidget *parent = 0);    ~MainWindow();private slots:    void on_viewFile_clicked();    void on_startDown_clicked();    void onFinished(QNetworkReply* reply);public slots:    void logWrite(QString log);    void finishDown();private:    Ui::MainWindow *ui;    QString mvpath;    QString module;    QString bqgUrl;    QString bookname;    QList<QString> pageList;    QNetworkAccessManager *netManager;    QString getSubStr(QString str,QString start_str,QString end_str,qint32 start_len,qint32 end_len);};#endif // MAINWINDOW_H

#include "mainwindow.h"#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :    QMainWindow(parent),    ui(new Ui::MainWindow){    ui->setupUi(this);    bqgUrl = "http://www.biquge.com/";    netManager = new QNetworkAccessManager(this);    connect(netManager,SIGNAL(finished(QNetworkReply*)),this,SLOT(onFinished(QNetworkReply*)));    logWrite("www.biquge.com/xxx/(xxx即是小说代码)");}MainWindow::~MainWindow(){    delete ui;}void MainWindow::on_viewFile_clicked(){    QString dir = QFileDialog::getExistingDirectory(this,"选择小说的存放路径:",".",QFileDialog::ShowDirsOnly);    ui->mvpath->setText(dir);}void MainWindow::on_startDown_clicked(){    mvpath = ui->mvpath->text();    if(mvpath.isEmpty()){        QMessageBox::warning(this,"错误","下载路径不能为空!");return;    }    module = ui->module->text();    if(module.isEmpty()){        QMessageBox::warning(this,"错误","小说代号不得为空!");return;    }    netManager->get(QNetworkRequest(QUrl(bqgUrl+module)));    ui->startDown->setEnabled(false);}void MainWindow::onFinished(QNetworkReply* reply){    pageList.clear();    QByteArray arr = reply->readAll();    QString content(arr);    QRegExp rx("/"+module+"/[0-9]{7,9}.html");    qint32 startPos = 0;    qint32 pos = content.indexOf(rx,startPos);    while( pos >= 0){        pageList.append(rx.cap(0));        pos = content.indexOf(rx,pos + rx.matchedLength());    }    reply->deleteLater();    LeaderThread * leader = new LeaderThread();    leader->setList(pageList);    leader->setParam(this,bqgUrl+module+"/",mvpath);    leader->setBookName(getSubStr(content,"<div id=\"maininfo\">","</h1>",51,0));    leader->start();}void MainWindow::logWrite(QString log){    ui->log->append(log);}QString MainWindow::getSubStr(QString str,QString start_str,QString end_str,qint32 start_len,qint32 end_len){    qint32 pos_start = str.indexOf(QRegExp(start_str),0);    if(pos_start == -1){        return "";    }    qint32 pos_end = str.indexOf(QRegExp(end_str),pos_start);    if(pos_end == -1){        return "";    }    return str.mid(pos_start+start_len,pos_end-end_len-pos_start-start_len);}void MainWindow::finishDown(){    ui->startDown->setEnabled(true);}

2、开辟一个管理下载的线程LeaderThread

#ifndef LEADERTHREAD_H#define LEADERTHREAD_H#include <QThread>#include "mainwindow.h"#include "downloadthread.h"#include <QtAlgorithms>#pragma execution_character_set("utf-8")class LeaderThread : public QThread{    Q_OBJECTpublic:    LeaderThread();    void setList(QList<QString>& list);    void setParam(QMainWindow* wnd,QString baseUrl,QString path);    void setBookName(QString bookname);signals:    void sendLog(QString log);    void finishDown();protected:    void run();    void openMuchTread(qint32 n,qint32 start_pos);private:    QList<QString> m_list;    QMainWindow* wnd;    QString baseUrl;    QString path;    QString bookname;};#endif // LEADERTHREAD_H

#include "leaderthread.h"LeaderThread::LeaderThread(){}void LeaderThread::run(){    QDir dir(path+"/tmp");    if(!dir.exists()){        dir.mkdir(path+"/tmp");    }    QString filename = path + "/" + bookname + ".txt";    if(QFile::exists(filename)){        QFile::remove(filename);    }    connect(this,SIGNAL(sendLog(QString)),wnd,SLOT(logWrite(QString)));    connect(this,SIGNAL(finishDown()),wnd,SLOT(finishDown()));    qint32 listSize = m_list.size();    for(qint32 i = 0;i < listSize ; i=i+25){        if((listSize-i)>0 && (listSize-i) < 25){            openMuchTread(listSize-i,i);        }else{            openMuchTread(25,i);        }    }    QFile file(filename);    if(!file.open(QFile::WriteOnly|QFile::Truncate)){        sendLog("小说全集打包失败,文件打开失败");return;    }    for(QString item : m_list){        QFile tmpfile(path + "/tmp/" + item);        if(!tmpfile.open(QFile::ReadOnly)){            sendLog("文件没有打开:"+item);return;        }        file.write(tmpfile.readAll());        file.write("\r\n\r\n\r\n");        tmpfile.close();        QFile::remove(path + "/tmp/" + item);        sendLog("打包临时文件:"+item);    }    file.close();    dir.rmdir(path + "/tmp");    QString logInfo;    logInfo = QString("打包完成,共下载了%1章").arg(m_list.size());    sendLog(logInfo);    finishDown();    quit();}void LeaderThread::setList(QList<QString>& list){    for(QString item : list){        int pos = item.indexOf(QRegExp("/"),1);        QString newStr = item.mid(pos+1,7);        if(!m_list.contains(newStr))            m_list.append(newStr);    }    qSort(m_list.begin(),m_list.end());}void LeaderThread::setParam(QMainWindow* wnd,QString baseUrl,QString path){    this->wnd = wnd;    this->baseUrl = baseUrl;    this->path = path;}void LeaderThread::openMuchTread(qint32 n,qint32 start_pos){    QList<DownloadThread*> downlist;    for(qint32 i = 0 ;i < n ;++i){        QString page = m_list.at(start_pos + i);        DownloadThread* downThread = new DownloadThread(wnd,baseUrl,page,path);        downlist.append(downThread);        downThread->start();    }    for(DownloadThread* tr : downlist){        tr->wait(10000);    }    downlist.clear();}void LeaderThread::setBookName(QString bookname){    this->bookname = bookname;}

3、单个下载的线程DownloadThread

#ifndef DOWNLOADTHREAD_H#define DOWNLOADTHREAD_H#include <QThread>#include <QtNetwork>#include "mainwindow.h"#pragma execution_character_set("utf-8")class DownloadThread : public QThread{    Q_OBJECTpublic:    DownloadThread();    DownloadThread(QMainWindow* wnd,QString baseUrl,QString page,QString path);protected:    void run();    QString getContent(QString html);    QString getSubStr(QString str,QString start_str,QString end_str,qint32 start_len,qint32 end_len);signals:    void sendLog(QString log);private:    QMainWindow* wnd;    QString baseUrl;    QString page;    QString path;};#endif // DOWNLOADTHREAD_H
#include "downloadthread.h"DownloadThread::DownloadThread(){}DownloadThread::DownloadThread(QMainWindow* wnd,QString baseUrl,QString page,QString path){    this->wnd = wnd;    this->baseUrl = baseUrl;    this->page = page;    this->path = path;}void DownloadThread::run(){    connect(this,SIGNAL(sendLog(QString)),wnd,SLOT(logWrite(QString)));    QNetworkAccessManager * manager = new QNetworkAccessManager(this);    QNetworkReply *reply = manager->get(QNetworkRequest(QUrl(baseUrl + page + ".html")));    QEventLoop eventLoop;    connect(reply,SIGNAL(finished()),&eventLoop,SLOT(quit()));    eventLoop.exec();    QByteArray arr = reply->readAll();    QFile file(path + "/tmp/" + page);    if(!file.open(QFile::WriteOnly))    {        sendLog("存储页面"+page+"失败");        return;    }    QString html(arr);    QString content = getContent(html);    file.write(content.toUtf8());    file.close();    delete reply;    delete manager;    quit();}QString DownloadThread::getSubStr(QString str,QString start_str,QString end_str,qint32 start_len,qint32 end_len){    qint32 pos_start = str.indexOf(QRegExp(start_str),0);    if(pos_start == -1){        return "";    }    qint32 pos_end = str.indexOf(QRegExp(end_str),pos_start);    if(pos_end == -1){        return "";    }    return str.mid(pos_start+start_len,pos_end-end_len-pos_start-start_len);}QString DownloadThread::getContent(QString html){    QString title = getSubStr(html,"<div class=\"bookname\">","</h1>",34,0);    QString content = getSubStr(html,"<div id=\"content\">","<div class=\"bottem2\">",43,70);    content.replace(QRegExp("&nbsp;")," ");    content.replace(QRegExp("<br/>"),"\r\n");    sendLog("下载完成:" + title);    return title + "\r\n\r\n" + content;}




0 0