C++ QT 多线程与进程学习笔记
一、进程管理(QProcess)
-
启动外部进程
-
核心类 :
QProcess
-
作用: 执行系统命令或外部程序,支持参数传递和输入输出控制。
示例代码
:
cpp
Copy
cppQString program = "/bin/ls"; // 指定可执行程序路径 QStringList arguments; // 参数列表 arguments << "-l" << "-a"; // 添加参数 QProcess *myProcess = new QProcess(parent); // parent 用于自动内存管理 myProcess->execute(program, arguments); // 同步执行(阻塞当前线程) // 或 myProcess->start(program, arguments); // 异步执行(非阻塞)
-
-
注意事项
- 使用
start()
异步执行时需监听started()
/finished()
信号。 - 通过
readAllStandardOutput()
和readAllStandardError()
获取输出。 - 设置工作目录:
myProcess->setWorkingDirectory(path);
- 错误处理:监听
errorOccurred(QProcess::ProcessError)
信号。
- 使用
二、多线程编程(QThread)
-
继承 QThread 实现线程
核心步骤
:
-
继承
QThread
,重写run()
方法。 -
在
run()
中执行耗时操作,通过信号与主线程通信。
代码模板
:
cpp
Copy
cppclass WorkerThread : public QThread { Q_OBJECT public: void run() override { // 耗时操作(如计算、文件读写) QString result = doWork(); emit resultReady(result); // 通过信号传递结果 } signals: void resultReady(const QString &s); };
-
-
线程启动与资源释放
cpp
Copy
cppWorkerThread *thread = new WorkerThread; thread->start(); // 启动线程 connect(thread, &WorkerThread::finished, thread, &QObject::deleteLater); // 自动释放内存
-
注意事项
- 不要直接调用
run()
:必须通过start()
启动线程。 - 避免 GUI 操作:子线程中禁止操作界面组件(需通过信号槽通信)。
- 资源释放 :设置线程对象的
AutoDelete
属性或手动deleteLater()
。
- 不要直接调用
三、线程同步与互斥
-
QMutex(互斥锁)
-
作用: 保护共享资源,防止多线程同时访问。
使用示例
:
cpp
Copy
cppQMutex mutex; int sharedData = 0; void ThreadA::run() { mutex.lock(); sharedData += 1; mutex.unlock(); }
-
-
QSemaphore(信号量)
-
作用: 控制对多个相同资源的访问(如缓冲区管理)。
示例
:
cpp
Copy
cppQSemaphore sem(5); // 初始化5个可用资源 void Worker::accessResource() { sem.acquire(); // 请求资源(可用资源减1) // 操作资源... sem.release(); // 释放资源(可用资源加1) }
-
-
其他同步机制
- QMutexLocker : 自动管理
QMutex
的锁定与解锁(推荐使用)。 - QWaitCondition: 线程间条件等待(如生产者-消费者模型)。
- QReadWriteLock: 区分读写操作,提高并发性能。
- QMutexLocker : 自动管理
-
避免死锁
- 按固定顺序加锁。
- 使用超时机制:
mutex.tryLock(timeout)
。
四、进程 vs 线程对比
特性 | 进程 | 线程 |
---|---|---|
资源开销 | 高(独立内存空间) | 低(共享进程资源) |
数据共享 | 需 IPC(如管道、套接字) | 直接共享内存(需同步) |
适用场景 | 隔离性要求高(如第三方应用调用) | 高并发任务(如数据处理) |
五、常见问题与最佳实践
信号槽连接类型
- 跨线程通信使用
Qt::QueuedConnection
(默认自动识别)。
线程优先级
- 设置优先级:
thread->setPriority(QThread::HighPriority);
调试技巧
- 使用
qDebug() << QThread::currentThreadId();
打印线程 ID。