简单的股票行情演示(一) - 实时标的数据

news2024/11/18 11:17:20
    • 一、概述
    • 二、效果展示
    • 三、实现代码
      • 1、行情数据中心
      • 2、数据拉取模块
      • 3、基础服务模块
      • 4、UI展示
    • 四、相关文章

原文链接:简单的股票行情演示(一) - 实时标的数据

一、概述

很长一段时间都有一个想法,使用QCP去做一个行情展示小事例,一直没有着手开发的原因主要是行情数据源的问题,毕竟稳定的数据才是核心,加上今年5月份有了小宝宝也一直比较忙。

最近得空研究了下用C++实现股票行情展示相关内容,主要策略是通过拉取网上一些免费的开源接口数据,然后存储到本地,在通过代码读取需要的日期数据进行展示。互联网拉取行情数据方法网上随手百度后会发现有一大堆,调取个别接口进行获取数据也是很方便的,比如通过新浪开源获取A股股票接口获取实时行情数据就很简单,浏览器url输入框中输入http://hq.sinajs.cn/list=sz002208,sh601318这段测试连接,按下回车,就会拿到list指定的两支股票数据,效果如下图所示。

需要特别注意:该接口拉取频繁后,会被后台403,所以本地需要做一些策略,尽可能减少无效拉取


尝到了简单的甜头之后,接下来就是疯狂百度、google,尽可能全面的整理开源的行情数据源,网上虽然文章很多,但是重复的内容特别多,讲的比较好的文章有新浪股票 api、股票数据 API 接口合集、实时行情API,通过看这几篇文章能大概了解到一些皮毛,简单使用不成问题。总的来说提供了一个可操作的入口,数据源的问题算是暂时得到一部分解决,至于其他更完善的数据后续文章会有介绍,是由开源软件提供,而且文档比较详细,之后更多的数据将会使用开源程序进行获取

实时行情数据有了之后,接下来就是C++侧代码实现,主要分为异步数据拉取、数据写入本地文件、数据层读取,回调给UI展示,本篇文章接下来的主要内容将会讲解怎么拉取数据、回调给UI等流程。

二、效果展示

如下效果图所示,是一个简单的多窗口程序,支持同时拉取多支股票实时行情数据并回调给UI。拿其中一个行情数据展示窗口为例来说明,数据源是来自新浪行情API接口,测试程序UI展示总共分上中下三段,上半部分主要是股票盘口数据,展示开收盘价格、实时成交量等,中段是股票买卖五档数据,最底下白色框中是数据源内容,也就是从互联网接口拉取后的数据。

正常情况下测试程序只会跑一个窗口,图示中多个窗口主要是为了观察方便。

三、实现代码

1、行情数据中心

要想实现数据复用,并减少Server压力,数据中心是必不可少的模块,举一个简单例子,当UI界面上展示的两支股票相同时,那么数据中心只会维护一支股票数据,并实时更新然后同步给两份UI界面。

如下代码所示,为行情中心接口类,其中展示了如何去订阅股票详情数据和取消订阅,IQuoteCall这是订阅者唯一标识,每一个想要获取数据的对象都应该是一个IQuoteCall、或者持有一个IQuoteCall

struct QUOTECENTER_EXPORT IQuoteCenter
{
public:
 virtual ~IQuoteCenter(){}

public:
 //订阅detail
 virtual void SubscribeDetail(IQuoteCall * observer, const SecurityInfo & security) = 0;
 virtual void UnSubscribeDetail(IQuoteCall * observer) = 0;

    .
    .
    .

 //取消所有数据订阅
 virtual void UnSubscribe(IQuoteCall * observer) = 0;

 .
 .
 .
};

IQuoteCall接口类中有一个UpdateDetail接口,通过重写该接口即可获取订阅的标的行情数据,切换标的时从新订阅即可,之前订阅的标的会被自动取消。

股票实时行情数据需要启动一个轮训任务,每隔3秒去请求一次当前订阅的所有标的数据,有了时间服务后,我们只需要抛一个任务对象和时间间隔,之后的定时触发操作则会自动被执行。

QuoteCenter::QuoteCenter()
{
 qRegisterMetaType<DetailCNItem>("DetailCNItem");
 qRegisterMetaType<QList<DetailCNItem>>("QList<DetailCNItem>");
 m_strTaskID = Services::TimerServiceInstance()->AddTask(&DoRequests, 3000);
    .
    .
    .
}

DoRequests函数比较重要,可谓之承上启下,关键桥梁作用,因此这里单独做下说明。

首先DoRequests是一个C函数,被行情模块注册到时间管理器中,该函数会在指定时间间隔后触发一次,每次任务触发我们都需要在主线程中构造一个任务请求工作者,并把任务执行完成后的触发信号与行情对象的接收槽函数绑定,之后把任务对象抛给网络请求服务即可。任务对象后续还会有更加详细的说明,具体参看对detail请求对象说明。

void DoRequests(long long mseconds)
{
 .
 .
 .
 DetailWorker * detail = new DetailWorker(securitys);
 QObject::connect(detail, &DetailWorker::Response
  , static_cast<QuoteCenter *>(Quote::QuoteCenterInstance()), &QuoteCenter::OnDetailResponse);
 RLNet::NetworkInstance()->AddTask(detail);
}

2、数据拉取模块

本地数据的唯一来源就是从网络拉取,为了程序运行流程起见,必须要运行在工作线程中,防止阻塞UI,我们开发此演示程序是基于Qt开发框架下,所以线程创建、线程交互将会变的很简单,具体细节接下来一步一步讲解。

线程池

既然用到Qt,那么线程池肯定也要用Qt的,这样我们开发起来会省很多力气,如下代码所示,简单的几行代码我们就搞出来一个线程池,我们只管往池子里丢任务,当池子中有空闲线程时就会帮我们处理任务,是不是非常nice。

void RLNetwork::AddTask(CommonWorker * task)
{
 // 添加任务
 QThreadPool::globalInstance()->start(task);
}

RLNetwork::RLNetwork()
{
 curl_global_init(CURL_GLOBAL_DEFAULT);
 // 线程池初始化,设置最大线程池数
 QThreadPool::globalInstance()->setMaxThreadCount(8);
}

RLNetwork::~RLNetwork()
{
 curl_global_cleanup();
}

任务对象

有了线程池后,我们只管创建需要的task,然后丢到池子中,任务的触发时机将交给Qt线程池进行管理,我们只需要关心任务中要干什么、任务结束后怎么通知给外部即可。

任务基类

为了减少大量重复代码,这里我们定义一个任务基类,基类中完成每个请求任务都需要操作的内容,然后把请求体和写入内容封装成接口,供子类重写。

抽象内容包括:

  1. libcurl请求初始化、参数配置和清理
  2. 回调函数取到返回数据后整理标准字符串转发给子类Write函数
class RLNETWORK_EXPORT CommonWorker : public QObject, public QRunnable
{
public:
 CommonWorker();
 ~CommonWorker();

public:
 virtual void run() override;

 virtual void Write(char * data, std::size_t len) = 0;
 virtual void DoRequest(CURL * curl) = 0;

 static size_t  CurlWriteCb(char *ptr, size_t size, size_t nmemb, void *userdata);

private:
};

Detail请求

说了这么多,终于到了最关键的detail请求环节,如下StockListWorker代码所示,当Detail请求完成后,通过Response信号通知外部任务已完成,标的detail存放在了filePath指定的文件中。

对于StockListWorker对象有以下几点需要注意:

  1. 构造于主线程中,并且请求完成信号与主线程中槽函数所绑定
  2. DoRequest、Write和信号函数均运行于工作线程中
  3. 任务基类中我们设置了setAutoDelete为true,因此所有的请求对象在执行完任务后都会析构
  4. 析构函数运行于工作线程中,与run函数所在线程一致
class RLNETWORK_EXPORT StockListWorker : public CommonWorker
{
 Q_OBJECT

public:
 StockListWorker(const QString & filePath);
 ~StockListWorker();

signals:
 void Response(const QString & filePath);

public:
 virtual void Write(char * data, std::size_t len) override;
 virtual void DoRequest(CURL * curl) override;

private:
 QString m_filePath;
 QFile m_file;
};

DoRequest函数是基类提供给我们重写发送请求使用,如下代码所示,展示了请求detail数据的过程,网络请求我们统一使用libcurl进行完成,不使用Qt网络库主要是觉着不好用。

void StockListWorker::DoRequest(CURL * curl)
{
 curl_easy_setopt(curl, CURLOPT_URL, StockListUrl);//准备发送request的url

 CURLcode res = curl_easy_perform(curl);
 if (res == CURLE_OK)
 {
  curl_off_t val = -1;
  curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME_T, &val);

  emit Response(m_filePath);
 }
 else
 {
  std::cout << "curl_easy_perform() failed: " << curl_easy_strerror(res);
 }
}

3、基础服务模块

市场服务

市场服务主要提供市场相关接口,如下代码所示,IsTradingStatus接口获取当前标的所属市场是否属于交易状态,根据市场状态我们可以过滤一些无效操作,比如A股不开盘时,不需要请求detail等。

struct BASICSERVICES_EXPORT IMarketService
{
 virtual ~IMarketService(){}

 virtual bool IsTradingStatus(const SecurityInfo & security, long long mseconds) const = 0;
 virtual bool IsTradingStatus(const QList<SecurityInfo> & securitys, long long mseconds) const = 0;
 ·
 ·
 ·
};

时间服务

时间管理器对于数据中心是相当重要的,因为有了时间维度后,我们才能去定制一批时间相关的任务,比如轮训任务、获取当前时间等。

本文中的股票实时detail数据就需要添加了一个轮训任务,因为没有长连接的加持,很多数据都需要我们自己去跟服务器要,虽然这样会增大服务器的压力,但是目前除过长连接外没有其他更好的方式去完成这件事。

struct BASICSERVICES_EXPORT ITimerService
{
 virtual ~ITimerService(){}

 virtual QString AddTask(const std::function<void(long long)> & fun, long internal = 3000) = 0;
 virtual bool HasTask(const QString &) = 0;
 virtual void RemoveTask(const QString &) = 0;
 virtual void ImmediatelyTask(const QString &) = 0;
 virtual long long GetCurrentStamp() const = 0;
 ·
 ·
 ·
};

4、UI展示

订阅股票detail

如下代码所示,通过行情中心我们可以很简单的去订阅标的数据,之后通过重写UpdateDetail接口拿数据就行,其他的我们统一不用操心。

void HqSimple::on_pushButton_pull_clicked()
{
 const QString & name = ui.comboBox->currentText();
 const QString & id = ui.comboBox->currentData().toString();
 const QStringList & items = id.split('_');

 SecurityInfo info;
 info.market = items.at(0);
 info.symbol = items.at(1);
 info.secType = "STK";

 Quote::QuoteCenterInstance()->SubscribeDetail(this, info);
}

每一个需要订阅行情数据的对象目前都是继承自IQuoteCall,或者持有一个IQuoteCall,本篇文章包括后续系列文章都会采用第一种方案来实现数据订阅,关于继承和包含的优缺点及使用场景问题大家可以自行斟酌,本篇文章所讲述案列数据类型较少,使用继承足以完成目标。

struct QUOTECENTER_EXPORT IQuoteCall
{
	virtual ~IQuoteCall(){}

	virtual void UpdateDetail(const DetailCNItem &) = 0;
	.
	.
	.
};

A股Detail数据定义

/*
0:  通用股份    // 名字;
1 : 5.050       // 今日开盘价
2 : 5.060       // 昨日收盘价
3 : 5.090       // 当前价格
4 : 5.110       // 今日最高价
5 : 5.030       // 今日最低价
6 : 5.090       // 竞买价,即 “买一” 报价;
7 : 5.100       // 竞卖价,即 “卖一” 报价;
8 : 3963000     // 成交的股票数,转手乘 100
9 : 20106078.000// 成交金额 (元),转万除 10000
10 : 52800       //“买一” 申请 52800 股
11 : 5.090       //“买一” 报价;
12 : 90600       //“买二” 申请 90600 股
13 : 5.080       //“买二” 报价;
14 : 98500       //..
15 : 5.070       //..
16 : 105200      //..
17 : 5.060       //..
18 : 127900      //..
19 : 5.050       //..
20 : 104400      //“卖一” 申报 104400 股
21 : 5.100       //“卖一” 报价;
22 : 99700       //“卖二” 申报 99700 股
23 : 5.110       //“卖二” 报价;
24 : 111800      //..
25 : 5.120       //..
26 : 87500       //..
27 : 5.130       //..
28 : 73300       //..
29 : 5.140       //..
30 : 2022 - 02 - 14  // 日期
31 : 11 : 18 : 56   // 时间
*/

struct STOCKDATA_EXPORT DetailCNItem : public SecurityInfo
{
 //0-9
 QString name;  //名字
 double open;  //今日开盘价
 double preClose; // 昨日收盘价
 double lastprice; // 当前价格
 double high;  // 今日最高价
 double low;   // 今日最低价
 double bid;   // 竞买价,即 “买一” 报价;
 double ask;   // 竞卖价,即 “卖一” 报价;
 double volumn;  // 成交的股票数,转手乘 100
 double amount;  // 成交金额 (元),转万除 10000
 
 struct AskBid
 {
  double price;//买/卖价
  double volumn;//买/卖量
 };

 QVector<AskBid> asks;//卖五档 //10-19
 QVector<AskBid> bids;//买五档 //20-29
 
 //30-31
 QString date; // 日期
 QString time; // 时间

 QString source; //原始数据

 DetailCNItem();
 DetailCNItem(const QString & str);
 DetailCNItem(DetailCNItem && other);

 void Clear();
};

刷新数据

UI数据刷新这里就比较简单了,文章最开始已经描述过UI数据分为上中下三部分,上部和下部就是简单文案设置,然后通过qss加了一些涨跌色配置,这里就简单展示下部分代码。

void HqSimple::UpdateDetail(const DetailCNItem & data)
{
 ui.label_open->setText(QString::number(data.open, 'f', 2));
 .
 .
 .
 ui.label_amount->setText(QString::number(data.amount, 'f', 2));

 m_pListmodel->SetAskBid(data);

 ui.textEdit->setText(QStringLiteral("原始数据:") + data.source);
}

盘口数据分为6列:买档、买价格、买数量、卖数量、卖价格和卖档。实现起来也比较简单,标准MVC即可搞定,代码中表现为QAbstractListModel+QListView+QStyledItemDelegate,其中M和V都比较简单,简单的进行绑定之后就可以,这里主要说下绘制界面用的QStyledItemDelegate,其中最为关键的就是paint函数,相信用过Qt一年半载的同学都比较熟悉,代码如下所示,绘制代码比较简单就不做说明了,不明白的同学进行留言或者私聊即可。

void AskBidDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
 const DetailCNItem & detail = index.model()->data(index).value<DetailCNItem>();

 //left
 int y = 15;
 int lwidth = option.rect.width() / 2;

 const QPoint & gPos = QCursor::pos();
 const QPoint & lPos = option.widget->mapFromGlobal(gPos);
 int t = 0;
 if (lPos.x() >= 0 && lPos.x() <= lwidth)
 {
  t = 1;
 }
 else if (lPos.x() >= lwidth && lPos.x() <= lwidth * 2)
 {
  t = 2;
 }

 {
  painter->fillRect(option.rect.adjusted(0, 0, lwidth, 0)
   , t == 1 && option.state.testFlag(QStyle::State_MouseOver) ? QColor(28, 109, 83) : QColor(39, 67, 62));

  const DetailCNItem::AskBid & bid = detail.bids.at(index.row());
  const QString & bidName = QStringLiteral("买%1").arg(index.row() + 1);
  painter->setPen(QColor(Qt::white));
  painter->drawText(10, option.rect.top() + y, bidName);
  painter->setPen(QColor(Qt::red));
  painter->drawText(60, option.rect.top() + y, PriceText(bid.price));

  const QString & volumnName = PriceText(bid.volumn);
  int volumW = painter->fontMetrics().width(volumnName);
  painter->setPen(QColor(Qt::white));
  painter->drawText(lwidth - volumW, option.rect.top() + y, volumnName);
 }

 //right
 {
  painter->fillRect(option.rect.adjusted(option.rect.width() / 2, 0, 0, 0)
   , t == 2 && option.state.testFlag(QStyle::State_MouseOver) ? QColor(28, 109, 83) : QColor(68, 48, 58));
  const DetailCNItem::AskBid & ask = detail.asks.at(index.row());

  const QString & volumnName = PriceText(ask.volumn);
  painter->setPen(QColor(Qt::white));
  painter->drawText(lwidth + 10, option.rect.top() + y, volumnName);

  painter->setPen(QColor(Qt::green));
  painter->drawText(option.rect.width() - 98, option.rect.top() + y, PriceText(ask.price));

  const QString & askName = QStringLiteral("卖%1").arg(index.row() + 1);
  painter->setPen(QColor(Qt::white));
  painter->drawText(option.rect.width() - 28, option.rect.top() + y, askName);
 }
}

讲到这里,股票行情展示程序也差不都完成了,从数据订阅、数据求情、数据缓存、数据回调和数据刷新大致都说了一遍,最后贴上项目工程截图,大家可以参考。

四、相关文章

  1. Qt 之股票组件 - 自选股 -- 列表可以拖拽、右键常用菜单
  2. Qt 之股票组件 - 股票检索 -- 支持搜索结果预览、鼠标、键盘操作
  3. QCustomplot使用分享(一) 能做什么事
  4. QCustomplot使用分享(二) 源码解读
  5. QCustomplot使用分享(三) 图
  6. QCustomplot使用分享(四) QCPAbstractItem
  7. QCustomplot使用分享(五) 布局
  8. QCustomplot使用分享(六) 坐标轴和网格线
  9. QCustomplot使用分享(七) 层(完结)

值得一看的优秀文章:

  1. 财联社-产品展示
  2. 广联达-产品展示
  3. Qt定制控件列表
  4. 牛逼哄哄的Qt库

如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!!
 


很重要--转载声明

  1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords

  2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。


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

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

相关文章

TiDB Cloud

TiDB Cloud 为什么选择TiDB 分布式数据库-多租户混合工作负载-在同一个数据库中 事务型&#xff1a;基于行的数据分析型&#xff1a;基于列的数据 弹性比例&#xff1a; 缩小-减少节点横向扩展-添加节点 基于“RAFT”的高可用性 每个数据段的3个可用区进行复制 多租户 什么…

DataGridXL 2.0 for JavaScript Crack

你的web开发好了&#xff0c;客户说我习惯用excel这样的表格&#xff0c;你们是否能开发像电子表格一样的功能&#xff1f; Web 应用程序的类似 Excel 的体验---DataGridXL 2.0 for JavaScript Crack 你已经构建了一个 Web 应用程序&#xff0c;但你的用户坚持使用 Excel。 类似…

一、ROS2简介

ros2相关简介 ROS2的前身是ROS&#xff0c;ROS即机器人操作系统&#xff08;Robot Operating System&#xff09;。但是ROS本身并不是一个操作系统&#xff0c;而是一个软件库和工具集。 Ros的出现解决了机器人各个组件的通信问题&#xff0c;后来越来越多的机器人算法也集成到…

漫谈信息模型(1)

简单地表达复杂的世界&#xff0c;这是各类思想家近千年来的追求。如何将人类在世界上观察到的结果进行概念化表达&#xff1f;又如何描述人造的复杂工具&#xff1f;这种探索成为人类文明进步的一个重要的驱动力。计算机的出现&#xff0c;推动了人类对现实事物进行概念化的描…

技术开发87

技术开发87 业务内容&#xff1a; . 冲床加工&#xff0c;高速冲床加工&#xff0c;省力化机械制作 . 铣床加工&#xff0c;食品机械制作 . 轮廓加工&#xff0c;钢丝加工 . 冲床模具制作 . 溶接 公司简介&#xff1a; 资本金&#xff1a;1000万日元&#xff08;约66元人…

文件数据丢失怎么办?推荐几款好用的文件恢复大师

众所周知&#xff0c;计算机在使用过程中难免会出现文件数据丢失的情况&#xff0c;这是一种非常正常的现象。但是遇到这种情况&#xff0c;很多时候我们不知道该如何去补救。特别是由于一些原因导致电脑被重启&#xff0c;这样不仅会对电脑造成一定影响&#xff0c;更重要的是…

2022年8月15日陌陌推荐算法工程师面试题5道|含解

8本电子书免费送给大家&#xff0c;见文末。 1、DeBERTa与BERT的区别 DeBERTa提出了两种改进BERT预训练的方法&#xff1a;第一种方法是分散注意机制&#xff0c;该机制使用两个向量分别对每个单词的内容和位置进行编码来表示每个单词&#xff0c;并使用分散矩阵计算单词之间…

本地传奇架设详细教程

十二堂今天给大家分享一篇技术文章&#xff0c;传奇架设教程。 教程讲的很详细&#xff0c;就是一个菜鸟都能学会如何架设传奇。 在管理工具&#xff0d;>服务中停止ssdpdiscoveryservic服务 一、准备软件DBCommander 2000 Pro和传奇服务端&#xff08;什么版本都行&#x…

设计模式之代理模式(十一)

目录 1. 静态代理 2. 动态代理 3. Cglib代理 代理模式&#xff1a;为一个对象提供一个替身&#xff0c;以控制对这个对象的访问。好处就是可以用来增强。 被代理的对象可以是 远程对象&#xff0c;创建开销大的对象 或者 需要安全控制的对象。 可以分为三类 静态代理动态代…

Robot Framework 自动化测试详解

一、Robot Framework 简介 1、界面自动化测试工具 界面自动化测试,即UI自动化测试,比较常见的工具有:QTP、AutoIt、Selenium等。 像QTP经历了很多版本,最新的版本好像叫UFT了。对初学者来说,录制回放是相当容易上手的,除了录制,QTP主要用VBScript脚本编写代码,同时有…

C/C++语言 9 —— 函数

把相同业务功能维度的代码有机的整合起来做成函数&#xff0c;这样做既可以方便反复调用&#xff0c;又可以在空间上节省代码行数。 函数的定义&#xff1a; 返回值类型 函数名(参数类型1 参数变量名1, ....参数类型N 参数变量N){ //此处参数为形参// 函数体.... } 如果不需…

外汇天眼:德国PPI利淡欧美镑美跌逾百点,美元涨近百点,黄金跌约20美元,关注美制造业指数

昨日重要因素影响 : 1.英媒&#xff1a;英国在继续购买俄罗斯石油 但称从其他国家进口 2.德国10月PPI月率低于市场预期 3.欧洲央行首席经济学家连恩&#xff1a;我们将在12月再次加息&#xff0c;不认为12月将是最后一次加息 4.穆迪&#xff1a;在需求降温的环境下&#xf…

Java标准输入输出流【转换流打印流】

➤ Java 输入输出IO流 全部导航 文章目录乱码转换【转换流】InputStreamReaderOutputStreamWriter打印流&#xff1a;PrintStreamPrintWriter类型默认设备System.in 标准输入InputStream键盘System.out 标准输出PrintStream显示器 System类的 public final static InputStream…

C++ 语法基础课4 —— 数组

文章目录1. 一维数组1.1 数组的定义1.2 数组的初始化1.3 访问数组元素(通过下标访问数组)1.4 练习1:1.5 练习21.6 练习31.7 练习41.8 练习4(难点)2. 多维数组2.1 练习11. 一维数组 1.1 数组的定义 数组的定义方式和变量类似 #include<iostream> #include<algorithm…

linux网络编程 - epoll边沿触发/水平触发内核实现代码分析

1、listen socket水平触发的poll函数调用 以服务器端epoll为例&#xff0c;加入监听、等待并接受连接、再次等待&#xff0c;会有3次检查是否有连接就绪的操作&#xff0c;分别是epoll_ctl、epoll_wait、epoll_wait。 1.1、epoll_wait(第1次调用) 等待就绪链表相关内核看前面发…

dropout 机制存在,对于同一句子的两次输出是不同的

SimCSE 提供了无监督&#xff08;上图 a&#xff09;和有监督&#xff08;上图 b&#xff09;两种架构&#xff0c;由于业务需要我们只用了无监督方式&#xff0c;其基本思路是&#xff1a; 1. 同一个 batch 内的数据两次输入模型。 2. 由于有 dropout 机制存在&#xff0c;对…

摩托车商城系统(基于javaweb开发的项目)

目录 前言 一、项目目录 二、效果图 2.1 首页面效果图 2.2 商品分类页面 ​​​​​​​2.3 热销栏页面 2.4 新品栏页面 2.5 购物狂欢栏页面 2.6 我的订单页面 2.7 个人中心页面 2.8 注册页面 2.9 用户登录页面 2.10 Admin后台管理主页面 2.11 Admin订单管理页面 2.12 A…

[附源码]SSM计算机毕业设计基于社区生鲜配送系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

万字总结线程池

本文将从背景、原理、架构、实现、参数状态等方面详细介绍percona-线程池。此外&#xff0c;还将简单介绍腾讯云企业级MySQL(CDB)内核技术--TXSQL&#xff0c;关于线程池的动态启停、负载均衡以及快速断连等优化。 「第一部分 背景」 社区版的MySQL的连接处理方法默认是为每个…

“信任机制”才是数字化时代发展中的精髓所在

2008年&#xff0c;美国次贷危机全面爆发并不断蔓延&#xff0c;最终席卷全球&#xff0c;酿成了世界性的金融危机。当年11月1日&#xff0c;一位署名为中本聪的人发表一篇《比特币&#xff1a;一种点对点的电子现金系统》论文提出了一种完全通过点对点技术实现的电子现金系统。…