Qt 三种启动多线程的方法

# Qt 三种启动多线程的方法

Qt 提供了多种实现多线程的方式,以下是三种最常用的方法:

## 1. QThread 子类化 (继承 QThread)

这是最传统的 Qt 多线程实现方式。

```cpp
// 1. 继承 QThread 并重写 run() 方法
class WorkerThread : public QThread
{
    Q_OBJECT
protected:
    void run() override {
        // 在这里执行耗时操作
        for(int i = 0; i < 100; i++) {
            qDebug() << "Thread working:" << i;
            sleep(1);  // 模拟耗时操作
        }
    }
};

// 使用
WorkerThread *thread = new WorkerThread();
thread->start();  // 启动线程
```

**特点**:
- 直接继承 QThread
- 重写 run() 方法
- 简单直接,但不够灵活

## 2. 移动 QObject 到线程 (推荐方式)

这是 Qt 推荐的方式,更符合事件驱动模型。

```cpp
// 1. 创建一个工作类继承 QObject
class Worker : public QObject
{
    Q_OBJECT
public slots:
    void doWork() {
        // 耗时操作
        for(int i = 0; i < 100; i++) {
            qDebug() << "Worker processing:" << i;
            QThread::sleep(1);
            emit progress(i);
        }
        emit finished();
    }
signals:
    void progress(int value);
    void finished();
};

// 2. 使用
QThread *thread = new QThread();
Worker *worker = new Worker();

// 将 worker 移动到新线程
worker->moveToThread(thread);

// 连接信号槽
connect(thread, &QThread::started, worker, &Worker::doWork);
connect(worker, &Worker::finished, thread, &QThread::quit);
connect(worker, &Worker::finished, worker, &Worker::deleteLater);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);

thread->start();  // 启动线程
```

**特点**:
- 更灵活,可以使用信号槽通信
- 符合 Qt 的事件循环模型
- 可以轻松实现线程间通信
- 是 Qt 推荐的方式

## 3. 使用 QtConcurrent (高级 API)

QtConcurrent 提供了高级函数式编程接口,适合简单的并行任务。

```cpp
#include

// 1. 定义一个普通函数
void heavyComputation(int iterations) {
    for(int i = 0; i < iterations; i++) {
        qDebug() << "Computing:" << i;
        QThread::sleep(1);
    }
}

// 2. 使用 QtConcurrent::run 启动线程
QFuture future = QtConcurrent::run(heavyComputation, 100);

// 可以监控进度
QFutureWatcher *watcher = new QFutureWatcher();
connect(watcher, &QFutureWatcher::finished, [](){
    qDebug() << "Computation finished";
});
watcher->setFuture(future);
```

**特点**:
- 最简单易用的 API
- 适合一次性任务
- 自动使用线程池
- 支持返回值 (通过 QFuture)
- 支持 Map/Reduce 等高级操作

## 方法对比

| 方法                | 适用场景                          | 优点                          | 缺点                          |
|---------------------|---------------------------------|-----------------------------|-----------------------------|
| 继承 QThread         | 简单线程任务                     | 直接控制线程生命周期          | 不够灵活,不能很好利用事件循环 |
| moveToThread        | 需要与主线程频繁交互的复杂任务     | 灵活,支持完整信号槽通信       | 代码结构稍复杂                |
| QtConcurrent        | 数据并行处理,一次性任务          | 简单易用,自动管理线程池       | 控制粒度较粗                  |

## 选择建议

1. **简单计算任务** → 使用 QtConcurrent
2. **需要持续运行的线程** → 使用 moveToThread
3. **需要精确控制线程行为** → 继承 QThread (但大多数情况下不推荐)

**最佳实践**:在大多数情况下,`moveToThread` 方式是最佳选择,它既保持了灵活性,又能充分利用 Qt 的信号槽机制。#牛客AI配图神器#
全部评论

相关推荐

发个面筋攒攒人品一面实习项目是什么?分布式锁 你都用过哪些? 你设置过期时间么? 如果抛出异常了 你的锁 还能删么?你说的redisson 和setnx 有什么区别?主线程 等待后面十个并发请求的完成之后 再处理主线程?你会怎么实现?你的分布式锁过期了 然后业务还没处理完 会产生什么情况?Redis持久化策略? 内存淘汰策略的呢?你都用过什么数据结构?线程中的wait 和 sleep的话有什么区别?创建线程都有哪些方式?线程池的核心参数? 最大线程数 指的是什么? 我现在没有工作队列 然后 10核心线程数 30最大线程数 现在15个线程进来 会怎么执行?集合的set元素可以重复么?key能重复么? 为什么不能重复?sql优化有什么思路?现在又100条数据 要你去进行修改 然后涉及三个表 如果有一个表修改失败你需要去回滚 你会怎么做?你说的tcc 本地事务不是也会影响到么 怎么解决?二面实习公司是干什么的 业务说一说针对项目难点或者说 遇到的不会的地方?Rocket的消息模型都知道那些?Rocketmq的 无序 顺序 事务 消息都说一下吧?泛型你怎么看Stream流循环和for循环 你怎么看JVM结构?双亲委派机制?垃圾回收器?@Transaction事务 的 传递方式? 失效场景? 为什么会失效?Inodb存储引擎么 你知道他是B+树 那么他和b树 和红黑树之间 优点在那里?ArrayList 和 LinkedList 的区别 适用场景?为什么会适用这样的场景?HashMap ConcurrentHashMap?你说了锁 那你说下锁升级 锁是怎么实现的?CAS你刚才也说了  他会有什么问题 怎么解决?线程池的话你用过哪些? 然后 参数都有什么 你会怎么设置? 为什么这样设置?Java io模型 你都知道什么? Nio怎么实现的?Mysql一条select语句的查询顺序MVC的处理流程?Java的异常? 运行时异常 和 非运行时异常呢?手撕sql一面完秒约二面 二面完约hr面
点赞 评论 收藏
分享
评论
点赞
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务