一 Qt線程與進程概述
線程與進程對比
特性 線程 (QThread) 進程 (QProcess) 內存空間 共享父進程內存 獨立內存空間 創建開銷 小 (幾MB) 大 (幾十MB) 通信方式 共享內存/信號槽 管道/套接字/文件 崩潰影響 導致整個進程終止 僅自身終止 適用場景 高并發任務、計算密集型 隔離第三方應用、安全需求
二 Qt線程
1. 基本概念
線程:程序執行的最小單元,共享相同內存空間
QThread:Qt中線程管理的核心類
線程安全:多線程訪問共享資源時需同步
?2. 創建方式(四種)
繼承QThread類,重寫run()方法
使用moveToThread將一個繼承QObject的子類對象移至線程,內部槽函數均在子線程中執行
使用QThreadPool,搭配QRunnable (線程池)
使用QtConcurrent(線程池)
n. 線程創建
1. QThread,重寫run()
#include <QThread>
#include <QDebug>class WorkerThread : public QThread {Q_OBJECT
protected:void run() override {for (int i = 0; i < 5; ++i) {qDebug() << "Thread working:" << i;sleep(1); // 模擬耗時操作}}
};// 使用
int main() {WorkerThread thread;thread.start(); // 啟動線程thread.wait(); // 等待線程結束return 0;
}
2.?moveToThread
#include <QObject>
#include <QThread>
#include <QDebug>class Worker : public QObject {Q_OBJECT
public slots:void doWork() {for (int i = 0; i < 5; ++i) {qDebug() << "Worker in thread:" << QThread::currentThreadId();QThread::sleep(1);}emit workDone();}
signals:void workDone();
};// 使用
int main() {QThread thread;Worker worker;worker.moveToThread(&thread); // 關鍵步驟QObject::connect(&thread, &QThread::started, &worker, &Worker::doWork);QObject::connect(&worker, &Worker::workDone, &thread, &QThread::quit);thread.start();thread.wait();return 0;
}
3.?QThreadPool(線程池)
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QThreadPool"
#include "MyTask.cpp"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mytask.cpp"
#include "QThreadPool"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//新建10個任務,提交給線程池//方式1: 全局線程池:一個項目中只有一個線程池,有時候整個項目有有可能有多個//QThreadPool *pool = QThreadPool::globalInstance();//方式2:新建線程池QThreadPool *pool = new QThreadPool;for(int i=0;i<10;i++){pool->start( new MyTask());}}MainWindow::~MainWindow()
{delete ui;
}}MainWindow::~MainWindow()
{delete ui;
}#include <QRunnable>
#include <QDebug>
#include <QThread>
class MyTask : public QRunnable
{//重寫run方法void run() override{qDebug()<< QThread::currentThread() << "running .....";}};
4.?QtConcurrent(線程池)
三 Qt進程
1. 基本概念
-
進程:獨立內存空間的程序實例
-
QProcess:用于啟動和控制外部程序
進程是一個應用程序被操作系統拉起來加載到內存之后從開始執行到執行結束的這樣一個過程。簡單來說,進程是程序(應用程序,可執行文件)的一次執行。進程通常由程序、數據和進程控制塊(PCB)組成。比如雙擊打開一個桌面應用軟件就是開啟了一個進程。
傳統的進程有兩個基本屬性:可擁有資源的獨立單位;可獨立調度和分配的基本單位。對于這句話我的理解是:進程可以獲取操作系統分配的資源,如內存等;進程可以參與操作系統的調度,參與CPU的競爭,得到分配的時間片,獲得處理機(CPU)運行。
進程在創建、撤銷和切換中,系統必須為之付出較大的時空開銷,因此在系統中開啟的進程數不宜過多。比如你同時打開十幾個應用軟件試試,電腦肯定會卡死的。于是緊接著就引入了線程的概念
四 sqlite數據庫
? sqlite十個輕量級的數據庫,如果要進行嵌入式的開發,像mysql,與Oracle像這樣的中大型關系庫是不太現實的,因為嵌入式大部分的工作,還是以輕量級的項目為主,盡可能的節約空間,完成項目,sqlite可以不用他的專屬服務器就可以使用,它可以以一個文件為庫,可以還可以用sql的語句,兼顧效率的同時,也極致的輕量化。
? 在此我認為只需要寫兩個項目即可,一是如何鏈接數據庫,二是如何進行增刪改查。
1. 連接數據庫
其實我建議將連接數據庫的語句單獨寫個類出來,這樣簡化操作,上上選。
1. 在我的project.pro的上方添加?
QT ? ? ? += core gui sql?
2. 引入頭
#include <QSqlDatabase> #include <QSqlError> //sql錯誤信息頭文件 #include <QSqlQuery> //sql查詢頭文件
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");// 鏈接數據庫db.setDatabaseName("D:/360MoveData/Users/HP/Desktop/sqlite_db/test.db");if (db.open() == false){qDebug() << "數據庫打開失敗";return;}else{qDebug() << "數據庫打開成功";// 新建tableQSqlQuery query;QString sql = "create table if not exists user(id int primary key, name varchar(20))";if (query.exec(sql)){qDebug() << "表格創建成功";// 向user插入數據sql = "insert into user(id, name) values(1, '張三')";if (query.exec(sql)){qDebug() << "數據插入成功";// 查詢數據sql = "select * from user";if (query.exec(sql)){qDebug() << "數據查詢成功";// 輸出到qDebugwhile (query.next()){qDebug() << query.value(0).toInt() << query.value(1).toString();}}else{qDebug() << "數據查詢失敗";}}else{qDebug() << "數據插入失敗";}}else{qDebug() << "表格創建失敗";qDebug() << query.lastError().text();}}
}
2. 增刪改查示例
這個寫了個dao來進行數據庫的處理,相信大家可以看的懂,其實不難。仔細看一看。
#include "studentdao.h"/*** @brief 構造函數* 獲取數據庫連接*/
StudentDAO::StudentDAO(): m_db(DatabaseManager::getInstance()->getDatabase())
{
}/*** @brief 添加學生* @param student 學生對象* @return 添加成功返回true,否則返回false*/
bool StudentDAO::addStudent(const Student &student)
{if (!m_db.isOpen()){qDebug() << "添加學生失敗:數據庫未連接";return false;}QSqlQuery query(m_db);// 使用參數化查詢,防止SQL注入query.prepare("INSERT INTO student (id, name) VALUES (:id, :name)");query.bindValue(":id", student.id());query.bindValue(":name", student.name());if (query.exec()){qDebug() << "添加學生成功:ID=" << student.id() << ", 姓名=" << student.name();return true;}else{qDebug() << "添加學生失敗:" << query.lastError().text();return false;}
}/*** @brief 刪除學生* @param id 學生ID* @return 刪除成功返回true,否則返回false*/
bool StudentDAO::deleteStudent(int id)
{if (!m_db.isOpen()){qDebug() << "刪除學生失敗:數據庫未連接";return false;}QSqlQuery query(m_db);query.prepare("DELETE FROM student WHERE id = :id");query.bindValue(":id", id);if (query.exec()){if (query.numRowsAffected() > 0){qDebug() << "刪除學生成功:ID=" << id;return true;}else{qDebug() << "刪除學生失敗:未找到ID為" << id << "的學生";return false;}}else{qDebug() << "刪除學生失敗:" << query.lastError().text();return false;}
}/*** @brief 更新學生信息* @param student 學生對象* @return 更新成功返回true,否則返回false*/
bool StudentDAO::updateStudent(const Student &student)
{if (!m_db.isOpen()){qDebug() << "更新學生失敗:數據庫未連接";return false;}QSqlQuery query(m_db);query.prepare("UPDATE student SET name = :name WHERE id = :id");query.bindValue(":name", student.name());query.bindValue(":id", student.id());if (query.exec()){if (query.numRowsAffected() > 0){qDebug() << "更新學生成功:ID=" << student.id() << ", 新姓名=" << student.name();return true;}else{qDebug() << "更新學生失敗:未找到ID為" << student.id() << "的學生";return false;}}else{qDebug() << "更新學生失敗:" << query.lastError().text();return false;}
}/*** @brief 根據ID查詢學生* @param id 學生ID* @return 學生對象,如果不存在返回空對象*/
Student StudentDAO::getStudentById(int id)
{Student student;if (!m_db.isOpen()){qDebug() << "查詢學生失敗:數據庫未連接";return student;}QSqlQuery query(m_db);query.prepare("SELECT id, name FROM student WHERE id = :id");query.bindValue(":id", id);if (query.exec() && query.next()){student.setId(query.value(0).toInt());student.setName(query.value(1).toString());qDebug() << "查詢學生成功:ID=" << student.id() << ", 姓名=" << student.name();}else{qDebug() << "查詢學生失敗:未找到ID為" << id << "的學生";}return student;
}/*** @brief 查詢所有學生* @return 學生對象列表*/
QList<Student> StudentDAO::getAllStudents()
{QList<Student> students;if (!m_db.isOpen()){qDebug() << "查詢所有學生失敗:數據庫未連接";return students;}QSqlQuery query("SELECT id, name FROM student", m_db);while (query.next()){Student student;student.setId(query.value(0).toInt());student.setName(query.value(1).toString());students.append(student);}qDebug() << "查詢所有學生成功,共" << students.size() << "條記錄";return students;
}