Qt 多线程编程:单例任务队列的设计与实现

引言:

在现代应用程序开发中,多线程编程已成为处理异步任务的标配。对于 GUI 应用而言,保持主线程的响应性尤为重要。本文将详细介绍一个基于 Qt 的单例任务队列实现方案,它通过线程池和单例模式,优雅地解决了后台任务管理的难题。

一、为什么需要任务队列?

在GUI应用中,我们经常需要执行一些耗时操作,如文件IO、网络请求、复杂计算等。如果直接在主线程中执行这些操作,会导致界面卡顿甚至无响应。理想的解决方案是将这些任务放到后台线程中执行。

但简单地为每个任务创建一个新线程会带来新的问题:线程创建和销毁的开销、线程数量过多导致的资源耗尽、任务执行顺序难以控制等。任务队列正是为解决这些问题而生。

二、核心架构设计

2.1 系统组件概览

我们的异步处理系统由两大核心组件构成:

单例任务队列系统
任务线程 TaskThread
单例模板 Singleton
任务队列管理
线程同步机制
异常安全处理
线程安全初始化
生命周期管理

2.2 任务队列线程(TaskThread)

TaskThread是整个系统的异步执行引擎,继承自Qt的QThread类,负责管理任务队列和执行任务。

  • 关键功能解析:
    1. 任务队列管理

      • 使用std::deque<TaskItem>存储任务,支持双端插入
      • 每个任务包含函数对象和任务类型
      • 任务类型可用于分类管理和批量清除
    2. 任务添加策略

      • immediate参数控制任务插入位置
      • true:插入队列头部(高优先级)
      • false:插入队列尾部(普通优先级)
    3. 线程同步机制

      • QMutex保护共享资源(任务队列)
      • QWaitCondition实现线程间通信
      • 无任务时线程休眠,有新任务时唤醒
  • 核心实现代码:
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <deque>
#include <functional>
#include <atomic>
#include <iostream>// 任务类型定义
using TaskType = int;
const TaskType ANY_TASK = -1;// 任务项结构体
struct TaskItem {std::function<void()> func;  // 任务函数TaskType type = 0;           // 任务类型
};// 任务线程类
class TaskThread : public QThread {Q_OBJECT
public:explicit TaskThread(QObject* parent = nullptr) : QThread(parent), stop_flag_(false) {}~TaskThread() override {stop();}// 添加任务到队列void addTask(std::function<void()> task, TaskType type = 0, bool immediate = false) {QMutexLocker locker(&mtx_condition_);if (stop_flag_) return;if (immediate) {tasks_.emplace_front(TaskItem{std::move(task), type});} else {tasks_.emplace_back(TaskItem{std::move(task), type});}condition_.wakeOne();}// 清除指定类型任务void clearTask(TaskType type = ANY_TASK) {QMutexLocker locker(&mtx_condition_);if (type == ANY_TASK) {tasks_.clear();} else {auto it = tasks_.begin();while (it != tasks_.end()) {if (it->type == type) {it = tasks_.erase(it);} else {++it;}}}}// 停止线程void stop() {{QMutexLocker locker(&mtx_condition_);if (stop_flag_) return;stop_flag_ = true;tasks_.clear();condition_.wakeAll();}wait();}// 启动线程void active() {start();}signals:void sigGenerateLogReport(const QString& report);protected:void run() override {while (true) {TaskItem task;{QMutexLocker locker(&mtx_condition_);// 等待任务或停止信号while (tasks_.empty() && !stop_flag_) {condition_.wait(&mtx_condition_);}// 检查退出条件if (stop_flag_ && tasks_.empty()) {return;}// 获取任务task = std::move(tasks_.front());tasks_.pop_front();}// 执行任务try {if (task.func) task.func();} catch (...) {// 异常处理逻辑std::cerr << "Task execution failed" << std::endl;}}}private:std::deque<TaskItem> tasks_;     // 任务队列QMutex mtx_condition_;           // 互斥锁QWaitCondition condition_;       // 条件变量std::atomic_bool stop_flag_;     // 停止标志
};

2.3 单例模板(Singleton)

Singleton模板确保全局只有一个TaskThread实例,提供安全、统一的访问入口

  • 关键技术亮点:
    • 使用互斥锁保证线程安全
    • 延迟初始化(Lazy Initialization)
    • 提供引用和指针两种获取方式
    • 注意避免拷贝构造(必须使用auto&Singleton::instance()
  • 单例实现核心:
// 单例模板
template <typename T>
class Singleton {
public:// 获取单例引用static T& instance() {std::call_once(init_flag_, []() {instance_ = new T();std::atexit(destroy);});return *instance_;}// 获取单例指针static T* ptr() {return instance_;}// 判断是否已销毁static bool isNull() {return instance_ == nullptr;}// 销毁单例static void destroy() {if (instance_) {delete instance_;instance_ = nullptr;}}private:Singleton() = delete;~Singleton() = delete;Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;static T* instance_;static std::once_flag init_flag_;
};

2.4 使用示例 (Main)

// 静态成员初始化
template <typename T>
T* Singleton<T>::instance_ = nullptr;template <typename T>
std::once_flag Singleton<T>::init_flag_;// 使用示例
void addLogGenerationTask() {Singleton<TaskThread>::instance().addTask([] {// 模拟日志生成(实际应用中可能是耗时操作)QString report = "System log report generated at " + QDateTime::currentDateTime().toString();// 通过信号发送结果emit Singleton<TaskThread>::ptr()->sigGenerateLogReport(report);}, 1);  // 类型1表示日志任务
}int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 启动任务线程Singleton<TaskThread>::instance().active();// 添加任务addLogGenerationTask();// 添加立即执行任务Singleton<TaskThread>::instance().addTask([] {std::cout << "Urgent task executed immediately!" << std::endl;}, 0, true);// 清除所有日志任务Singleton<TaskThread>::instance().clearTask(1);// 程序结束时自动停止线程QObject::connect(&app, &QCoreApplication::aboutToQuit, [] {Singleton<TaskThread>::instance().stop();});return app.exec();
}

三、工作原理详解

3.1 生产者-消费者模型

整个系统基于经典的生产者-消费者模型:

  • 生产者:向任务队列添加任务的线程(通常是主线程)
  • 消费者TaskThread线程,负责从队列中取出并执行任务
  • 共享资源:任务队列std::deque
  • 同步机制QMutexQWaitCondition

这种模型的优势在于解耦了任务提交和执行,使代码更易维护和扩展。

3.2 任务执行流程

下面是run()方法的核心逻辑:

void TaskThread::run()
{while (!is_exit_) {QMutexLocker locker(&mtx_condition_);if (tasks_.empty()) {condition_.wait(&mtx_condition_);} else {auto func = tasks_.front().func;if (func) {func();}tasks_.pop_front();}}
}

执行流程:

  1. 线程进入循环,检查退出标志
  2. 加锁后检查队列是否为空
  3. 队列为空时调用wait()释放锁并休眠
  4. 有新任务时被唤醒,获取队首任务执行
  5. 执行完毕后解锁,继续循环

3.3 线程同步机制

同步是多线程编程的难点,我们的实现采用了以下策略:

  • 添加任务时

    void TaskThread::addTask(...)
    {QMutexLocker locker(&mtx_condition_);// 添加任务到队列condition_.wakeAll();
    }
    
  • 清除任务时

    void TaskThread::clearTask(TaskType type)
    {QMutexLocker locker(&mtx_condition_);// 过滤并清除指定类型任务condition_.wakeAll();
    }
    
  • 线程等待时

    condition_.wait(&mtx_condition_);
    

这种设计确保:

  1. 任何时候只有一个线程可以操作任务队列
  2. 队列为空时线程不会空转,节省CPU资源
  3. 新任务添加或队列变更时,工作线程能及时响应

四、解决的核心痛点

  • 解耦任务提交与执行:业务代码只需关注任务逻辑,无需关心线程管理
  • 线程资源复用:避免频繁创建/销毁线程的开销
  • 任务优先级控制:支持紧急任务插队执行
  • 类型化任务管理:可按类型分类和批量清除任务
  • 线程安全:完善的同步机制确保多线程环境下的稳定性

4.1 主线程阻塞问题

在GUI应用中,耗时操作会导致界面冻结无响应。单例任务队列通过将任务转移到后台线程执行,保持界面流畅。

传统方式

void generateReport() {// 在主线程执行耗时操作QString report = createComplexReport(); // 界面冻结!showReport(report);
}

使用任务队列

void generateReportAsync() {Singleton<TaskThread>::instance().addTask([] {QString report = createComplexReport();QMetaObject::invokeMethod(qApp, [report] {showReport(report); // 回到主线程更新UI});});
}

4.2 资源竞争与线程安全

多线程环境下,资源竞争是常见问题。我们的方案通过:

  1. 单例模式确保全局唯一访问点
  2. 互斥锁保护任务队列
  3. 条件变量实现高效线程等待

4.3 任务管理混乱

传统异步代码常面临任务管理难题

  • 无法取消已提交任务
  • 缺乏优先级控制
  • 没有任务分类机制

我们的解决方案提供:

// 添加紧急任务(插队执行)
addTask(urgentTask, HIGH_PRIORITY, true);// 清除所有日志任务
clearTask(LOG_TASK_TYPE);// 安全停止所有任务
stop();

五、典型应用场景

  • 后台文件操作:如备份、压缩、批量重命名等
  • 数据处理:如解析大型JSON/XML文件、统计分析等
  • 网络任务:如下载文件、同步数据等
  • 定时任务:如定期清理缓存、生成报表等

5.1 后台日志处理

void logSystemExample() {// 添加日志生成任务Singleton<TaskThread>::instance().addTask([] {// 在后台线程执行QString logContent = generateSystemLog();saveToFile(logContent);// 通知主线程emit logSaved(logContent);}, LogTask);// 添加紧急日志上传Singleton<TaskThread>::instance().addTask([] {if (!uploadCriticalLogs()) {retryUpload(); // 自动重试机制}}, CriticalLogTask, true); // 立即执行
}

5.2 数据处理流水线

void dataProcessingPipeline() {// 第一阶段:数据清洗(后台执行)Singleton<TaskThread>::instance().addTask([] {auto data = loadRawData();return cleanData(data);}, DataCleanTask);// 第二阶段:数据分析(依赖清洗结果)Singleton<TaskThread>::instance().addTask([] {auto result = analyzeData();emit analysisComplete(result);}, DataAnalysisTask);
}

5.3 定时任务调度

// 创建定时器
QTimer* dailyReportTimer = new QTimer(this);// 每天生成报告
connect(dailyReportTimer, &QTimer::timeout, [] {Singleton<TaskThread>::instance().addTask([] {generateDailyReport();}, ReportTask);
});dailyReportTimer->start(24 * 60 * 60 * 1000); // 24小时

5.4 后台执行文件备份

在后台执行文件备份任务,完成后通知主线程更新进度或显示结果。

// 在主线程中提交备份任务(例如用户点击"紧急备份"按钮后)
Singleton<TaskThread>::instance().addTask([this] {// 源文件路径与备份路径QString sourceDir = "/home/user/documents";QString backupDir = "/backup/docs_" + QDateTime::currentDateTime().toString("yyyyMMddHHmmss");// 创建备份目录QDir().mkpath(backupDir);// 执行文件拷贝(模拟耗时操作)bool success = false;QFileInfoList files = QDir(sourceDir).entryInfoList(QDir::Files);for (const QFileInfo &file : files) {// 检查是否需要中断(可根据实际需求添加取消逻辑)if (QThread::currentThread()->isInterruptionRequested()) {success = false;break;}// 拷贝文件success = QFile::copy(file.filePath(), backupDir + "/" + file.fileName());if (!success) break;// 模拟处理延迟QThread::msleep(100);}// 任务完成后通过信号通知主线程emit sigBackupCompleted(success, backupDir);},TaskThread::Other,  // 任务类型:其他类型true);              // 紧急任务,插入队首优先执行

这个例子展示了几个关键点:

  1. 通过单例模式获取全局任务队列实例,无需传递线程指针
  2. 使用lambda表达式封装备份逻辑,包含文件IO等耗时操作
  3. 通过sigBackupCompleted信号将结果(备份是否成功、备份路径)传递给主线程
  4. 设置immediate=true确保紧急备份任务优先执行
  5. 支持任务中断检查(通过isInterruptionRequested

六、高级特性与优化策略

6.1 批量任务处理

当任务数量大且执行快时,批量处理可显著减少锁竞争:

void run() {const int BATCH_SIZE = 10; // 每次处理10个任务std::vector<TaskItem> batch;while (!stop_flag_) {{QMutexLocker locker(&mtx_condition_);// 批量获取任务for (int i = 0; i < BATCH_SIZE && !tasks_.empty(); ++i) {batch.push_back(std::move(tasks_.front()));tasks_.pop_front();}}// 批量执行for (auto& task : batch) {task.func();}batch.clear();}
}

6.2 优先级队列扩展

使用std::priority_queue替代std::deque实现多级优先级

// 任务优先级定义
enum Priority {Immediate,  // 最高优先级High,Normal,Low
};struct TaskItem {std::function<void()> func;Priority priority;
};// 优先队列比较器
struct TaskCompare {bool operator()(const TaskItem& a, const TaskItem& b) {return a.priority > b.priority; // 值越小优先级越高}
};// 使用优先队列
std::priority_queue<TaskItem, std::vector<TaskItem>, TaskCompare> tasks_;

6.3 异常安全增强

健壮的异常处理防止单个任务崩溃整个线程:

void run() {while (true) {// ... [获取任务]try {if (task.func) task.func();} catch (const std::exception& e) {qCritical() << "Task failed:" << e.what();emit taskFailed(task.type, e.what());}catch (...) {qCritical() << "Unknown task error";emit taskFailed(task.type, "Unknown error");}}
}

6.4 任务进度反馈

// 定义带进度的任务函数
using ProgressFunc = std::function<void(int)>; // 进度回调(0-100)
void addTaskWithProgress(std::function<void(ProgressFunc)> func, ...);// 使用示例
addTaskWithProgress([](ProgressFunc progress) {for (int i = 0; i < 100; ++i) {// 执行部分任务progress(i); // 反馈进度QThread::msleep(50);}
});

七、最佳实践与注意事项

7.1 生命周期管理

MainThreadSingletonTaskThreadinstance()创建实例addTask()执行任务destroy()stop()停止确认MainThreadSingletonTaskThread

关键规则

  1. main函数退出前调用Singleton<TaskThread>::destroy()
  2. 在QApplication析构前停止任务线程
  3. 任务中避免持有界面对象的长期引用

7.2 跨线程通信规范

// 安全更新UI的两种方式:// 方式1:使用QMetaObject
Singleton<TaskThread>::instance().addTask([] {QString result = processData();QMetaObject::invokeMethod(qApp, [result] {updateUI(result); // 在主线程执行});
});// 方式2:通过信号槽(自动排队)
class Controller : public QObject {Q_OBJECT
public slots:void handleResult(const QString& result) {updateUI(result);}
};// 在任务中发射信号
emit taskCompleted(result); // 自动跨线程传递

7.3 资源清理策略

清理类型选择

// 清除所有任务
clearTask(ANY_TASK);// 仅清除网络请求任务
clearTask(NETWORK_TASK);// 清除低优先级任务
clearTask(LOW_PRIORITY_TASK);

八、扩展与未来方向

8.1 线程池集成

对于CPU密集型任务,可扩展为线程池架构

class TaskThreadPool {
public:TaskThreadPool(int size = QThread::idealThreadCount()) {for (int i = 0; i < size; ++i) {auto thread = new TaskThread(this);threads_.push_back(thread);thread->active();}}void addTask(std::function<void()> task, Priority pri = Normal) {// 负载均衡算法选择线程auto thread = selectThread();thread->addTask(task, pri);}private:std::vector<TaskThread*> threads_;
};

8.2 任务依赖管理

实现有向无环图(DAG) 管理复杂任务依赖:

数据加载
数据清洗
特征提取
数据验证
模型训练

8.3 持久化任务队列

添加磁盘持久化支持,防止应用崩溃时任务丢失:

void saveQueueToDisk() {QMutexLocker locker(&mtx_condition_);QFile file("task_queue.dat");file.open(QIODevice::WriteOnly);QDataStream out(&file);for (const auto& task : tasks_) {out << task.type;// 序列化任务函数(需要特殊处理)}
}

九、完整实现与使用示例

9.1 基础用法

// 初始化
Singleton<TaskThread>::instance().active();// 添加普通任务
Singleton<TaskThread>::instance().addTask([] {qDebug() << "Normal task executed";
}, NORMAL_TASK);// 添加紧急任务
Singleton<TaskThread>::instance().addTask([] {qDebug() << "Urgent task executed first!";
}, URGENT_TASK, true);// 清理特定任务
Singleton<TaskThread>::instance().clearTask(NORMAL_TASK);// 安全退出
QCoreApplication::aboutToQuit.connect([] {Singleton<TaskThread>::destroy();
});

9.2 实际应用案例

异步图片处理

void processImages(const QStringList& imagePaths) {for (const auto& path : imagePaths) {Singleton<TaskThread>::instance().addTask([path] {// 在后台线程处理QImage image(path);image = applyFilters(image);// 保存处理结果QString outputPath = generateOutputPath(path);image.save(outputPath);// 通知主线程emit imageProcessed(outputPath);}, IMAGE_PROCESSING_TASK);}
}

结语:

单例任务队列架构通过统一的任务调度中心高效的线程管理,解决了现代应用开发中的关键异步处理难题。本文介绍的技术方案具有:

  1. 高可靠性:异常安全处理和线程同步保障
  2. 灵活扩展:支持优先级、批量处理和任务分类
  3. 易于集成:简洁的API和单例访问模式
  4. 资源高效:单线程处理大量任务

这种架构特别适合以下场景:

  • GUI应用保持界面响应
  • 服务器应用处理并发请求
  • 数据处理流水线
  • 定时任务调度系统

学习资源:

(1)管理教程
如果您对管理内容感兴趣,想要了解管理领域的精髓,掌握实战中的高效技巧与策略,不妨访问这个的页面:

技术管理教程

在这里,您将定期收获我们精心准备的深度技术管理文章与独家实战教程,助力您在管理道路上不断前行。

(2)软件工程教程
如果您对软件工程的基本原理以及它们如何支持敏捷实践感兴趣,不妨访问这个的页面:

软件工程教程

这里不仅涵盖了理论知识,如需求分析、设计模式、代码重构等,还包括了实际案例分析,帮助您更好地理解软件工程原则在现实世界中的运用。通过学习这些内容,您不仅可以提升个人技能,还能为团队带来更加高效的工作流程和质量保障。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88712.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88712.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenEuler操作系统中检测插入的USB设备并自动挂载

OpenEuler操作系统中检测插入的USB设备并自动挂载 项目需求&#xff1a;工控机上openeuler操作系统是无界面版本的&#xff0c;在工控机上连接了激光雷达&#xff0c;当激光雷达采集完数据&#xff0c;我们要将采集数据导入u盘&#xff0c;故需要在工控机上插入u盘&#xff0c;…

《Spring 中上下文传递的那些事儿》Part 11:上下文传递最佳实践总结与架构演进方向

&#x1f4dd; Part 11&#xff1a;上下文传递最佳实践总结与架构演进方向 经过前面几篇文章的深入探讨&#xff0c;我们已经系统性地学习了 Spring 应用中上下文传递的各种技术原理、常见问题以及解决方案。从 Web 请求上下文到异步任务、从多租户隔离到日志脱敏&#xff0c;…

使用云虚拟机搭建hadoop集群环境

使用云虚拟机搭建hadoop集群环境 安装jdk17 配置docker网络 docker network create --subnet172.18.0.0/16 hadoop 172.18.0.0&#xff1a;这是子网的网络地址&#xff0c;也就是这个网络的起始地址。/16&#xff1a;这是子网掩码&#xff08;Network Mask&#xff09;&#x…

【机器学习】吴恩达机器学习课程代码作业-Python版本

吴恩达老师的机器学习课程作业是MATLAB版本&#xff08;Octave&#xff09;的&#xff0c;现在有点过时了&#xff0c;我参考了几位大牛的代码&#xff0c;将作业改成了Python3.6版本&#xff0c;并做了中文注释&#xff0c;推荐使用Jupyter notebook。Python作业使用了原版数据…

2025年人工智能、虚拟现实与交互设计国际学术会议

重要信息 官网&#xff1a;www.aivrid.com 时间&#xff1a;2025年10月17-19日 地点&#xff1a;中国-东莞 部分介绍 征稿主题 包括但不限于&#xff1a; 生物特征 模式识别 机器视觉 专家系统 深度学习 智能搜索 自动编程 智能控制 智能机器…

SHA-256算法流程分析与详解——Github工程结合示例和动画演示

近日笔者在学习区块链的相关知识&#xff0c;接触到SHA-256算法&#xff0c;这里做一个知识梳理和总结。 强烈推荐大家自行去学习下面链接github上的工程&#xff0c;作者的动画演示和解释做的非常出色&#xff0c;逻辑非常清晰&#xff0c;B站搬运的对应的油管的讲解视频也放…

CSPNet: A New Backbone that can Enhance Learning Capability of CNN (CSP模块)

3. Method 方法 3.1 Cross Stage Partial Network 跨阶段局部网络 3.1.1 Cross Stage Partial Network 跨阶段局部网络 3.1.1.1 ResNet 和 DenseNet 的优缺点主流的卷积神经网络&#xff08;CNN&#xff09;架构&#xff0c;如ResNet [8]、ResNeXt [37]、DenseNet [11]&#x…

前端学习4:小白入门注册表单的制作(包括详细思考CSS、JS实现过程)

这篇我们来做一个简单表单&#xff0c;即常见的注册页面吧~学习完这篇我们将学习到Input、label、CSS伪类、CSS入门、更多的JS操作等。。一、首先明确需求&#xff1a;直接模仿常见的注册页面&#xff0c;包括&#xff1a;用户名、Email、性别&#xff08;单选按钮男/女&#x…

强化学习 (RL) 新突破:超越游戏,走向复杂现实决策

强化学习 (RL) 新突破&#xff1a;超越游戏&#xff0c;走向复杂现实决策 强化学习&#xff08;Reinforcement Learning&#xff0c; RL&#xff09;作为人工智能的核心范式之一&#xff0c;历经数十年的发展&#xff0c;正迎来一场深刻的范式转移。曾以战胜人类顶尖选手的Alph…

2025年6-7月AI领域关键进展:从药物研发到全球监管--AI深度融入产业与社会

2025年6月至7月&#xff0c;人工智能领域继续以惊人速度发展&#xff0c;在技术突破、行业应用、政策法规、企业战略及学术研究等方面取得了一系列重要里程碑。以下为关键动态&#xff1a;一、技术突破&#xff1a; AI向生命科学和认知科学纵深挺进DeepMind启动AI设计药物人体试…

【TOOL】ubuntu升级cmake版本

文章目录一、下载cmake脚本二、安装一、下载cmake脚本 在编译新工程时遇到cmake版本过低的情况&#xff0c;到 cmake官网 下载指定cmake安装脚本&#xff1a; 若需下载指定版本&#xff0c;见上图右上角蓝框。 二、安装 # 赋予可执行权限 sudo chmod x cmake-3.31.8-linux-x8…

GMSK调制解调系统的matlab性能仿真,对比维特比解调,1bit差分解调,2bit差分解调

目录 1.前言 2.算法运行效果图预览 3.算法运行软件版本 4.部分核心程序 5.算法仿真参数 6.算法理论概述 7.参考文献 8.算法完整程序工程 1.前言 GMSK(Gaussian Minimum Shift Keying&#xff0c;高斯最小频移键控)是一种连续相位调制技术&#xff0c;基于MSK调制改进而…

SQL138 连续两次作答试卷的最大时间窗

SQL138 连续两次作答试卷的最大时间窗 问题分析 找出2021年至少有两天作答的用户计算每个用户连续两次作答的最大时间窗基于历史数据预测在这个时间窗内平均会做多少套试卷 版本1 with-- 功能​&#xff1a;筛选2021年至少有两天作答的用户及其作答记录-- 子查询找出2021年…

TensorFlow2 study notes[2]

文章目录tf.autodiff.ForwardAccumulatorreferencestf.autodiff.ForwardAccumulator the function can be used to achieve the Computation of Jacobian-vector products with forward-mode autodiff. primals is variables need to watch.tangents is direction vector. …

稳定币将成为新时代的重要金融工具

在数字经济加速渗透的今天,加密货币作为一种新型价值载体,正深刻改变着全球金融的运作逻辑。其中,稳定币与非稳定币构成了加密货币生态的两大支柱,二者在设计逻辑、应用场景和市场表现上呈现出显著差异。 稳定币锚定法定货币 稳定币是一类以法定货币、大宗商品或其他资产…

Constants

本节是《Solidity by Example》的中文翻译与深入讲解&#xff0c;专为零基础或刚接触区块链开发的小白朋友打造。我们将通过“示例 解说 提示”的方式&#xff0c;带你逐步理解每一段 Solidity 代码的实际用途与背后的逻辑。 Solidity 是以太坊等智能合约平台使用的主要编程语…

五镜头倾斜摄影相机的技术优势与应用原理

倾斜摄影技术作为三维实景建模的核心手段&#xff0c;其硬件设计直接影响数据采集效率与模型质量。在众多镜头配置方案中&#xff0c;五镜头结构&#xff08;下视前、后、左、右四个倾斜视角&#xff09;已成为行业主流选择。这一设计并非偶然&#xff0c;而是基于严苛的技术需…

ThinkSound V2版 - 一键给无声视频配音,为AI视频生成匹配音效 支持50系显卡 一键整合包下载

ThinkSound 是阿里通义实验室开源的首个音频生成模型&#xff0c;它能够让AI像专业“音效师”一样&#xff0c;根据视频内容生成高度逼真、与视觉内容完美契合的音频。 ThinkSound 可直接应用于影视后期制作&#xff0c;为AI生成的视频自动匹配精准的环境噪音与爆炸声效&#x…

如何从0开始构建自己的第一个AI应用?(Prompt工程、Agent自定义、Tuning)

一、前言 从0开始基于自定义Agent构建AI应用&#xff0c;涉及从创建智能Agent到使用、测试及优化提示词等一系列步骤。前置&#xff1a;什么是LLM、Prompt、Mcp和Agent&#xff1f; 二、步骤一&#xff1a;规划和设计AI应用 在创建AI应用之前&#xff0c;你需要明确应用的目标…

Java ThreadLocal详解:从原理到实践

Java ThreadLocal详解&#xff1a;从原理到实践&#xff08;图解极简示例&#xff09; 一、什么是ThreadLocal&#xff1f;——线程的"专属储物柜" ThreadLocal 是 Java 提供的线程本地存储机制&#xff0c;通俗来说&#xff0c;它能为每个线程创建一个独立的变量副本…