智能控制,高效节能。ZLG致远电子能源智慧管理解决方案

面对楼宇及建筑群能源管理与设备控制的复杂需求,ZLG致远电子推出了一套能源智慧管理解决方案。该方案集设备管理、任务调度和数据可视化于一体,不仅实现数据的实时监控与分析,还助力系统节能降耗。 ZLG致远电子能源智慧管理解决方案 在ZLG致远电子能源智慧管理解决方案中,用户可以通过ZWS云平台、GCOM80-2NET边缘计算网关、EM-1000高性能工控整机和TKM显控一体机系列生态产品,实现对各种能源设备的有效控制、数据的实时监控和分析、系统的节能降耗等关键需求。这些产品和技术的结合,不仅提高了能源利用效率,也为用户带来了更加智能化、便捷化的能源管理体验。 图1 ZLG致远电子能源智慧管理解决方案 ZWS云平台 ZWS云平台,全称为:ZLG Web Service云计算服务平台,是一个标准通用的物联网云端平台型服务系统。它为用户提供了设备管理、任务调度、数据可视化管理等功能。通过这个平台,用户可以方便地进行设备的在线管理和监控,执行不同的任务指令,并对收集到的数据进行可视化展示。 GCOM80-2NET边缘计算网关 为了实现高效的设备通信和数据处理,致远电子推出了8路RS485转以太网边缘计算网关GCOM80-2NET。这款网关可以帮助用户轻松实现Modbus等协议的边缘解析,减少了需要在云端进行二次处理的工作压力,提高了数据处理的效率。 EM-1000储能网关 EM-1000储能网关是致远电子专为新能源储能系统设计的一款高性能、多接口通讯管理设备。作为应用现场调度的中心,EM-1000储能网关承担着整个管理中心的数据边缘计算和任务调度管理,它能够在现场进行复杂的数据处理和任务分配,从而减轻云端服务器的压力,提高系统的响应速度和稳定性。 图2 EM-1000储能网关 TKM系列显控一体机 7寸的TKM系列显控一体机是致远电子针对工业应用领域开发的“显示”+“控制”一体化解决方案终端产品,它为该解决方案提供了云后台和终端数据同步显示与控制的功能。这种一体化的设计使得用户可以在一个界面上完成对整个系统的监控和管理,大大提高了操作的便捷性和效率。 图3 TKM系列显控一体机 除了有线连接管理方案外,致远电子还推出了无线化管理方案。这一方案适用于那些难以布线或者需要灵活移动的场合,提供了更为灵活和便捷的管理方式。 图4 ZLG致远电子能源智慧无线化管理解决方案

基于Java爬取微博数据(四) 获取 图片 or 视频

基于Java爬取微博数据四 获取 图片 or 视频 图片 or 视频转存 图片 or 视频注意点 前面已经讲述了基于 Java 爬取微博正文列表内容,微博用户主页内容以及导出爬取到的微博数据等操作,那么下面讲述一下如何处理微博正文中的图片/视频等内容。 图片 or 视频 对于微博正文来说,图片和视频不能同时存在,也就是说你的微博只能选择发9张以内的图片或者发1个视频,那么在爬取微博正文数据时,想要获取微博中的图片/视频该怎么操作呢?我们首先来看一下微博正文中图片或者视频的一些特点,选择任意一篇微博正文,利用浏览器工具选取任意一张图片 这里可以看到图片的链接。这里需要说明的是微博正文中的图片链接是做过防盗处理的,你直接复制图片链接到浏览器是无法打开的,但是你可以通过 Java 代码来转存 图片。 同样的方法,利用浏览器工具的抓取功能获取微博正文视频内容地址,视频内容是可以直接放在浏览器打开的,但是需要注意的是视频内容的链接地址有个有效期参数 Expires ,如果超过有效期再打开会提示 403 错误码 这里获取的视频链接地址通常是这样的 //locallimit.us.sinaimg.cn/o0/RSkMM0NElx08f30vCBPO01041200MgYx0E010.mp4?label=mp4_720p&template=1280x720.25.0&media_id=5036768815153197&tp=8x8A3El:YTkl0eM8&us=0&ori=1&bf=4&ot=h&lp=0000tfMx8&ps=mZ6WB&uid=66f6G2&ab=,8013-g0,3601-g27&Expires=1716360984&ssig=8XIVHnvPwu&KID=unistore,video 没有请求头 http 或者 https ,那么你可以直接将该链接放在浏览器,浏览器会自动适应请求头,视频内容是可以直接播放的。另外微博的默认请求头就是安全请求头 https 到这里关于微博正文中的图片 or 视频的大概情况介绍完了,下面可以转存图片 or 视频 转存 图片 or 视频 如果你需要微博正文中的图片 or 视频的话,那么你可以通过 Java 的方式获取图片 or 视频 内容,并转存到其他地方,这里我转存到本地电脑,整个 main 函数的代码如下 DemoWeiBoDown.java package com.ruoyi.web.controller.demo.controller; import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; /** * dongao * 2024/5/20 * 5月 */ public class DemoWeiBoDown { public static void main(String[] args) { String imageUrl = "

Modbus-TCP——Libmodbus安装和使用(Ubuntu22.04)

1、简介 Modbus是一种通信协议,广泛用于工业自动化和过程控制领域,允许不同设备之间进行数据交换。libmodbus是一个用于 Modbus 协议的开源库,主要用于开发和实现 Modbus 协议的客户端和服务器应用程序。libmodbus 以 C 语言编写,提供了一个简单易用的接口,用于处理 Modbus 通信。 2、安装 获得Libmodbus。 git clone https://github.com/stephane/libmodbus.git 安装 automake、autoconf、libtool 以及 gcc。 sudo apt-get install automake autoconf libtool gcc 生成配置脚本。 ./autogen.sh 配置、编译和安装。 ./configure make sudo make install 3、使用 tests提供了一些测试服务器和客户端。在两个shell中允许下面程序: ./unit-test-server ./unit-test-client

队列数据结构(顺序表示-数组)C语言版

1.Queue.h头文件 #include<stdio.h> #include<stdlib.h> #define MAX_SIZE 5 typedef struct { int data[MAX_SIZE]; int front; int rear; }Queue; //初始化 void InitQueue(Queue* q); //判断队空 int isEmpty(Queue* q); //判断队满 int isFull(Queue* q); //元素入队 void PushQueue(Queue* q,int val); //元素出队 int PopQueue(Queue* q); //获取队头元素 int getFront(Queue* q); //获取队尾元素 int getrear(Queue* q); 2.Queue.c源文件函数实现代码 #include"Queue.h" //初始化 void InitQueue(Queue* q) { q->front = 0; q->rear = 0; } //判断队空 int isEmpty(Queue* q) { return q->front == q->rear; } //判断队满 int isFull(Queue* q) { return (q->rear + 1) % MAX_SIZE == q->front;//(4+1)%5 MAX_SIZE == 5 } //元素入队 void PushQueue(Queue* q, int val) { if (isFull(q)) { printf("

机器学习线性回归算法——原理+python详细代码解析(sklearn)

线性回归算法作为经典的机器学习算法之一,拥有极为广泛的应用范围,深受业界人士的青睐。该算法主要用于研究分析响应变量如何受到特征变量的线性影响。其通过构建回归方程,借助各特征变量对响应变量进行拟合,并且能够利用回归方程进行预测。鉴于线性回归算法较为基础、简单,所以比较容易入门。 一、线性回归算法的基本原理 线性回归算法是一种较为基础的机器学习算法,基于特征(自变量、解释变量、因子、协变量)和响应变量(因变量、被解释变量)之间存在的线性关系。 线性回归算法的数学模型为:y=α+β1x1+β2x2+…+βnxn+ε 矩阵形式为:y=α+Xβ+ε 假定特征之间无多重共线性;误差项εi(i=1,2,…,n)之间相互独立,且均服从同一正态分布N(0,σ2),σ2是未知参数,误差项满足与特征之间的严格外生性假定,以及自身的同方差、无自相关假定。响应变量的变化可以由α+Xβ组成的线性部分和随机误差项i两部分解释。对于线性模型,一般采用最小二乘估计法来估计相关的参数,基本原理是使残差平方和最小,残差就是响应变量的实际值与拟合值之间的差值。 二、案例讲解 我们用于分析的数据是“数据4.1”文件,它是XX生产制造企业1994-2021年的profit(营业利润水平)、invest(固定资产投资)、labor(平均职工人数)、rd(研究开发支出)数据。下面我们以profit为响应变量,以invest、labor、rd为特征变量,开展线性回归算法。 1 导入分析所需要的模块和函数 导入pandas、numpy、matplotlib、seaborn、statsmodels、sklearn等模块。其中,pandas、numpy用于数据读取、数据处理、数据计算;matplotlib.pyplot、seaborn、sklearn中的LinearRegression用于构建线性回归模型;train_test_split用于把样本随机划分为训练样本和测试样本;mean_squared_error、r2_score模块分别用于计算均方误差(MSE)和可决系数,评价模型优劣。 import pandas as pd#载入pandas模块,并简称为pd import numpy as np#载入numpy模块,并简称为np import matplotlib.pyplot as plt#载入matplotlib.pyplot模块,并简称为plt import seaborn as sns#载入seaborn模块,并简称为sns from sklearn.linear_model import LinearRegression#载入LinearRegression模块 from sklearn.model_selection import train_test_split#载入train_test_split模块 from sklearn.metrics import mean_squared_error, r2_score#载入mean_squared_error, r2_score模块 2 数据读取及观察 首先需要将提供的数据文件【回复:数据4.1】放入安装Python的默认路径位置,并从相应位置进行读取,在Spyder代码编辑区输入以下代码并运行: data=pd.read_csv('C:/Users/Administrator/.spyder-py3/数据4.1.csv') # 读取数据4.1.csv文件 注意,因用户的具体安装路径不同,设计路径的代码会有差异,用户可以在“文件”窗口查看路径及文件对应的情况,如图。建议这样复制绝对路径,否则报错,找不到文件路径。 data.info() # 观察数据信息。运行结果为: 数据集中共有25个样本(25 entries, 0 to 24)、5个变量(total 5 columns)。5个变量分别是year、profit、invest、labor、rd,均包含25个非缺失值,其中year、labor的数据类型为整数型(int64),profit、invest、rd的数据类型为浮点型(float64)。数据文件中共有3个浮点型(float64)变量、2个整型(int64)变量,数据内存为1.1KB。 3 描述性分析 在进行数据分析时,当研究者得到的数据量很小时,可以通过直接观察原始数据来获得所有的信息。但是,当得到的数据量很大时,就必须借助各种描述性指标来完成对数据的描述工作。用少量的描述性指标来概括大量的原始数据,对数据展开描述的统计分析方法被称为描述性统计分析。 data.describe()#对数据集进行描述性分析 data.describe().round(2)#只保留两位小数 data.describe().round(2).T#只保留两位小数并转置 data.mean()#对数据集中的变量求均值 data.var()#对数据集中的变量求方差 data.std()#对数据集中的变量求标准差 data.cov()#对数据集中的变量求协方差矩阵 描述性分析的常用函数

Maven命令传pom或者jar异常

上传命令:mvn deploy:deploy-file -Durl=http://****:****/repository/chntdrools7741-releases -DrepositoryId=**** -Dfile=D:/tempRepo/org/kie/kie-api-parent/7.69.0.Final/kie-api-parent-7.69.0.Final.pom -DpomFile=D:/tempRepo/org/kie/kie-api-parent/7.69.0.Final/kie-api-parent-7.69.0.Final.pom 问题一: Cannot deploy artifact from the local repository: D:\tower\tempRepo\org\kie\kie-api-parent\7.69.0.Final\kie-api-parent-7.69.0.Final.pom 解决:把pom换个目录。比如到D盘下 问题二: The goal you specified requires a project to execute but there is no POM in this directory (D:\). Please verify you invoked Maven from the correct directory. 解决:找到项目路径下带有pom的路径

【HTML】为网页添加表单(控件)

1、表单 表单控件:包含了具体的表单功能项,如单行文本输入框、密码输入框、复选框、提交按钮、重置按钮等。 提示信息:一个表单中通常需要包含一些说明性的文字,提示用户进行填写和操作。 表单域:相当于一个容器,用来容纳所有的表单控件和提示信息。 2、创建表单 <form action="url地址" method="提交方式" name="表单名称"> 各种表单控件 </form> 表单控件:表单控件是表单的核心部分,常见的表单控件有、、。 action:action属性用于指定接收并处理表单数据的服务器程序的url地址。 method:method属性用于设置表单数据的提交方式,其取值为get或post。 name:name属性用于指定表单的名称,以区分同一个页面中的多个表单。 3、input控件 浏览网页时经常会看到单行文本输入框、单选按钮、复选框、提交按钮、重置按钮等,要想定义这些元素就需要使用input控件。 <input type="控件类型"/> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>input控件</title> </head> <body> <form action="#" method="post"> 用户名: <!--text单行文本输入框--> <input type="text" value="张三" maxlength="6" /><br /><br /> 密码: <!--password密码输入框--> <input type="password" size="40" /><br /><br /> 性别: <!--radio单选按钮--> <input type="radio" name="sex" checked="checked" />男 <input type="radio" name="sex" />女<br /><br /> 兴趣: <!--checkbox复选框--> <input type="checkbox" />唱歌 <input type="checkbox" />跳舞 <input type="

黑神话:悟空游戏用的什么服务器?

黑神话:悟空游戏用的什么服务器?《黑神话:悟空》游戏使用的是基于云计算的强大服务器,具体型号和配置未公开。这些服务器在游戏发布初期就表现出极强的处理能力和稳定性,尽管同时在线人数一度突破百万,但整体运行仍然十分稳定。下面将详细介绍相关技术细节和性能表现: 1.服务器的基本配置 高性能计算:根据Steam平台的记录,《黑神话:悟空》在开售不到一小时内,同时在线玩家数量便突破了100万,峰值达到了140万。这要求服务器具备极高的处理能力,能够同时处理大量玩家的请求和数据交换。 大容量存储:预载阶段,Steam下载使用的带宽量最高达到70Tbps,预载大小为118.04GB,需要的空间为128.68GB。这意味着服务器需要具备非常大的存储容量,以应对海量数据的传输和存储需求。 2.服务器的技术特点 高并发处理:为了应对大量玩家同时在线的情况,《黑神话:悟空》的服务器采用了高并发处理技术。这不仅包括高效的CPU和内存资源,还涉及优化的网络调度和负载均衡机制,确保每个玩家的游戏体验都是流畅和稳定的。 快速恢复机制:开售后不久,由于玩家数量剧增,Steam服务器一度崩溃,但很快得以恢复。这种快速恢复机制是现代云计算服务器的标准配置,能够在出现故障时迅速进行切换和备份,最大程度减少玩家的不便。 3.服务器的优化措施 带宽管理:考虑到游戏的巨大下载量和在线玩家数量,服务器采取了动态带宽管理措施。根据实时流量和需求调整带宽分配,确保所有玩家都能得到足够的下载和上传速度。 分布式架构:采用分布式计算架构,多个服务器节点协同工作,分担处理任务。这种设计不仅提高了整体的处理能力,还增强了系统的冗余和可靠性。 4.服务器的安全性能 数据安全:对于如此大规模的在线游戏,数据安全至关重要。《黑神话:悟空》的服务器采用了先进的加密技术和多层次的安全策略,确保玩家信息和游戏数据的安全。 网络防护:考虑到DDoS攻击等网络安全威胁,服务器具备强大的网络防护能力,能够及时检测并抵御各种网络攻击,保障游戏的正常运行和玩家的权益。 5.服务器的扩展能力 模块化设计:随着游戏内容的更新和玩家数量的增加,服务器可以快速扩展其计算和存储能力。模块化设计使得在需要时可以方便地增加新的硬件和资源。 灵活的配置调整:根据不同的市场和玩家需求,服务器配置可以进行灵活调整。从计算资源到网络带宽,都可以根据实际情况进行优化配置。 关于黑神话:悟空游戏用的什么服务器相关问题已为大家进行了详细介绍,《黑神话:悟空》所使用的服务器通过其高性能、高稳定性、优秀的扩展性和强大的安全防护措施,为全球玩家提供了卓越的游戏体验。更多服务器相关内容,请关注Raksmart!

2020 位示图

2020年网络规划设计师上午真题解析36-40_哔哩哔哩_bilibili 假设某计算机的字长为32位,该计算机文件管理系统磁盘空间管理采用位示图(bitmap),记录磁盘的使用情况。若磁盘的容量为300GB,物理块的大小为4MB,那 么位示图的大小为( )个字。 要计算位示图的大小,首先需要确定磁盘中有多少个物理块,然后再计算位示图需要多少位,最后将这些位转化为字数。 计算物理块的数量: 磁盘容量为 300 GB = 300×1024×1024×1024300 \times 1024 \times 1024 \times 1024300×1024×1024×1024 字节。物理块的大小为 4 MB = 4×1024×10244 \times 1024 \times 10244×1024×1024 字节。因此,物理块的数量为: 块数=300×1024×1024×10244×1024×1024=300×1024×10244=300×256=76800块\text{块数} = \frac{300 \times 1024 \times 1024 \times 1024}{4 \times 1024 \times 1024} = \frac{300 \times 1024 \times 1024}{4} = 300 \times 256 = 76800 \text{块}块数=4×1024×1024300×1024×1024×1024​=4300×1024×1024​=300×256=76800块 计算位示图的位数: 每个物理块对应位示图中的一位,因此位示图的总位数就是物理块的数量,即 76800 位。 计算位示图的字数: 计算机的字长为 32 位,因此每个字能存储 32 位。位示图的字数为: 字数=7680032=2400字\text{字数} = \frac{76800}{32} = 2400 \text{字}字数=3276800​=2400字 因此,位示图的大小为 2400 个字。

将Web应用部署到Tomcat根目录的三种方法

将应用部署到Tomcat根目录的三种方法 将应用部署到Tomcat根目录的目的是可以通过"http://[ip]:[port]"直接访问应用,而不是使用"http://[ip]:[port]/[appName]"上下文路径进行访问。 方法一:(最简单直接的方法) 删除原 webapps/ROOT 目录下的所有文件,将应用下的所有文件和文件夹复制到ROOT文件夹下。 方法二: 删除原webapps/ROOT 目录下的所有文件,修改文件conf/server.xml,在Host节点下增加如下Context的内容配置: <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false"> ...... <Context path="" docBase="/data/myapps/bertram" reloadable="false" /> </Host> 注意: 1)path 的值设置为空; 2)应用不要放到tomcat的webapps目录下(如上述配置是放到自定义的文件夹myapps内的),否则访问时路径会有问题; 3)docBase指定到绝对路径。 如配置此设置后重启tomcat,如果docBase指向的是war文件,则会自动将war解压到 webapps/ROOT 目录;如果docBase指向的是应用已解压好的目录,如 docBase="/data/myapps/bertram“,则tomcat不会生成 webapps/ROOT 目录(这种情况下,这样就可以不用删除 webapps/ROOT 目录,但 webapps/ROOT 目录内的内容是无法访问的),访问时将直接使用docBase指定的目录。 方法三: 与方法二类似,但不是修改全局配置文件conf/server.xml,而是在conf/Catalina/localhost目录下增加新的文件ROOT.xml(注意大小写),文件内容如下: <?xml version="1.0" encoding="UTF-8"?> <Context path="" docBase="/data/myapps/bertram" reloadable="true"> </Context>

RM惯性测量单元IMU

在Robomaster比赛中,一般各大参赛队会在机器人的云台上搭载IMU,用以反馈云台的yaw轴和pitch轴的角度和角速度。 需要注意的是,尽管依靠云台电机6020的编码器同样可以实现以上数据的获取,但是由于云台控制对于灵敏度和精度的要求比较高,而云台电机编码器反馈的数据分辨率较低,并且速度数据波动较大,用它来做控制并不能够达到很好的效果,所以目前的主流方案依然是通过IMU的数据来做云台的闭环控制。 IMU的选型方案非常多,从几十到几千乃至上万不等。一般IMU内部会包含陀螺仪和加速度计,陀螺仪用来反馈角速度和计算位姿,加速度计用于反馈线速度,陀螺仪和加速度各自提供三个轴向的速度数据,所以一般这种IMU被称为六轴IMU。基于不同原理去制作的陀螺仪和加速度计,能够达到的精度范围也有一定的区别。 但是对于IMU来说,总会有一个难以克服的问题,即累积误差。由于IMU通过是通过对内部的陀螺仪获取的角速度数据对时间进行积分获取角度数据的,无论一个陀螺仪的精度有多高,总是会在每个时刻产生一些误差,随着积分效应,误差逐渐累积,最后就会产生累积误差。 为了解决累积误差问题,一般厂家会在IMU内部再集成一个三轴磁力计,从而构成一个所谓的九轴IMU。磁力计的作用是对IMU计算出的位姿定期进行较准,从而解决累积误差。但是磁力计不适合在电磁环境复杂的场合下使用,如果附近有能够产生强磁场的设备,会对磁力计的数据产生非常大的影响。 可以在下图中看到,比较常用的微机械陀螺仪(MEMS)其累积误差水平大概在每小时10°到100°。但是由于实际上每局比赛时间并没有那么长,所以其实累积误差造成的影响并不是特别严重,没有必要为了过高的精度要求而去购买特别贵的陀螺仪。 关于IMU的选型,不同的队伍有着不同的方案,而且一般来说都经过了若干次的迭代。 IMU选型上的坑很多,其中最严重的问题就是由于各种原因引发的复位/离线问题。在这种情况下,失去反馈的云台会立刻失控,从而发生“疯头”。 以下针对IMU总结一些需要注意的要点 确保供电稳定,如果供电电压有较大的波动可能会引发IMU掉线确保物理防护,在赛场上的冲撞/弹丸打击可能会造成IMU的移位/掉线确保陀螺仪量程,如果撞击产生了超出陀螺仪量程的大角速度,可能会引发云台偏移的问题确保线路连接,保证通信线路电连接良好,尤其是当硬件方案涉及到比较长的走线时IMU会受到温度影响,如果要在冬天时把机器人带到室外,记得采取一定的保温措施(比如加热电阻) 以下是一些防范IMU离线引发严重问题的方案 准备电机闭环方案,检测到IMU离线后可以自动/手动切换成电机编码器反馈在云台上装载多个IMU,检测到一个离线后将反馈源切换成另一个采用官方开发板/自研开发板上集成的IMU,相比独立的IMU模块来说风险更小 最后推荐一个讲IMU的知乎专栏,有兴趣的同学可以看一看。https://zhuanlan.zhihu.com/p/41299359 开发板板载IMU 官方提供的开发板自带IMU,用户手册中的介绍如下 如果要使用开发板板载IMU,则必须将开发板固定在云台上可以同时随着yaw轴与pitch轴运动的位置。板载IMU的需要自己完成姿态解算,姿态解算是通过SPI读取MPU6500的寄存器数据后,将三轴加速度计和三轴陀螺仪的数据进行数据融合,解算出当前的位姿,其中为了能够使用矩阵进行快速的运算,需要将欧拉角转换成四元数。 姿态解算的推导涉及到比较复杂的数学过程,这里就不加以太多的介绍了,有兴趣的可以自己去看下面的博客。 姿态解算 姿态解算-CSDN博客 mpu6050姿态解算与卡尔曼滤波(1)数学_mpu6050姿态解算与卡尔曼滤波(1)数学-CSDN博客 滤波 姿态估计(1)——互补滤波(Complementary filter )-CSDN博客 四元数 彻底搞懂四元数-CSDN博客 牛顿迭代快速求根 牛顿迭代法快速寻找平方根 | Matrix67: The Aha Moments 官方车代码里面同样有解算的代码,并且有多种算法。下面这段代码是一个禁用了磁力计数据的算法,也是我自己以前移植到自己的工程里进行过测试的,由于当时我发现磁力计读取到的数据干扰很大,于是选择了禁用了磁力计数据的算法,只使用加速度计和陀螺仪进行数据融合。其中invSqrt是运用牛顿迭代法快速求平方根,是用于归一化处理的,官方给的注释在我看来已经已到位了,因此在这里不去加更多的注脚。 void mahony_ahrs_updateIMU(struct ahrs_sensor *sensor, struct attitude *atti) { float recipNorm; float halfvx, halfvy, halfvz; float halfex, halfey, halfez; float qa, qb, qc; gx = sensor->wx; gy = sensor->wy; gz = sensor->wz; ax = sensor->ax; ay = sensor->ay; az = sensor->az; mx = sensor->mx; my = sensor->my; mz = sensor->mz; // Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation) if (!

图文详解ThreadLocal:原理、结构与内存泄漏解析

目录 一.什么是ThreadLocal 二.ThreadLocal的内部结构 三.ThreadLocal带来的内存泄露问题 ▐ key强引用 ▐ key弱引用 总结 一.什么是ThreadLocal 在Java中,ThreadLocal 类提供了一种方式,使得每个线程可以独立地持有自己的变量副本,而不是共享变量。这可以避免线程间的同步问题,因为每个线程只能访问自己的ThreadLocal变量。通过ThreadLocal为线程添加的值只能由这个线程访问到,其他的线程无法访问,因此就避免了多线程之间的同步问题 使用ThreadLocal时,通常需要实现以下步骤: 初始化:创建ThreadLocal变量。 private static ThreadLocal<T> threadLocal = new ThreadLocal<>(); 设置值:使用set(T value)方法为当前线程设置值。 threadLocal.set(value); 获取值:使用get()方法获取当前线程的值。 T value = threadLocal.get(); 移除值:使用remove()方法在线程结束时清除ThreadLocal变量,以避免内存泄漏。 threadLocal.remove(); 在下面这个示例中,在主线程中存储了一个整形的10,新建一个线程后去取这个值是取不到的,因为该值只属于主线程,故输出为null public class ThreadLocalExample { private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>(); public static void main(String[] args) { // 设置线程局部变量的值 threadLocal.set(10); // 这个值在其他线程中是取不到获取的 new Thread(() -> { Integer value = threadLocal.get();//null System.out.println("Thread value: " + value); }).start(); } } 二.

【MySQL进阶之路】数据库的操作

目录 创建数据库 字符集和校验规则 查看数据库支持的字符集 查看数据库支持的字符集校验规则 指定字符集和校验规则 在配置文件中配置 查看数据库 显示创建语句 修改数据库 删除数据库 数据库的备份和恢复 备份整个数据库 备份特定表 备份多个数据库 备份所有数据库 MySQL服务的链接情况 个人主页:东洛的克莱斯韦克-CSDN博客 MySQL基础:【MySQL进阶之路】MySQL基础——从零认识MySQL-CSDN博客 创建数据库 create database 数据库的名称; create database 是关键字后面跟上数据库的名称,表示创建数据库 create database if not exists 数据库的名称; 在中间加上if not exists ,表示如果要创建的数据库已存在则不报错。 字符集和校验规则 字符集是字符的集合,它定义了用于表示文本数据的符号和这些符号的编码。校验规则定义了字符集中字符的比较和排序规则。 查看数据库支持的字符集 show charset; 查看数据库支持的字符集校验规则 show collation; 指定字符集和校验规则 create database 数据库名称 charset=字符集 collate=校验规则; charset= 后面表示要添加的字符集。collate= 后面表示要添加的校验规则。如果只指定了字符集,MySQL服务端会自动匹配对应的校验规则。相反,如果只指定了校验规则,MySQL服务端会自动匹配对应的字符集。 在配置文件中配置 可以在配置文件中配置默认的字符集和校验规则。 vim /etc/my.cnf 先打开该配置文件,然后在该配置文件中添加 character-set-server=字符集 collation-server=校验规则 如果创建数据库时指定了相关选项,就按指定的来,如果没有就按配置文件的来~ 查看数据库 show databases; 查看MySQL服务中已创建的数据库。 显示创建语句 show create database 数据库名; 显示创建该数据库时用了哪些SQL语句。

【C语言】数据在内存中的存储方式 - 别出心裁版(内含大小端字节序)

文章目录 前言1. 整数在内存的存储方式1.1 原码、反码和补码 2. 大小端字节序和字节序的判断2.1 什么是大小端字节序2.2 为什么会有大小端字节序2.3 判断字节序问题 3. 浮点数在内存中的存储3.1 练习3.2 浮点数的存储方式3.2.1 浮点数的存储过程3.2.2 浮点数的读取过程 前言 在编写代码的同时,你是否好奇或者思考过数据在内存中是以什么样的方式存储的。也许你会回答说,数据在内存中不就是二进制的形式表示的。这句话一点也没错,可再往深一步探讨,内存又是如何以二进制的形式来组织数据的呢? 数据分为整型家族(短整型、整型、长整型),浮点数家族(单精度浮点数、双精度浮点数),当然字符类型也可归为整型家族的成员。这些数据在内存中是以一样的规则去存储的,还是各自有一套规则呢? 本文我们就来一起探索一下数据在内存之后的神秘故事,相信在听完本文后,你对计算的世界兴趣又会上升到一个新的高度。 1. 整数在内存的存储方式 整数在内存中有三种表示形式:原码、反码、补码 那什么原码、反码和补码呢?接下来就给大家讲解一下。 1.1 原码、反码和补码 整数分为无符号整数和有符号整数。 相信大家在字里行间中已经猜到了一些意思, 无符号整数:说大白话,就是没有符号的整数,也就是正整数。 有符号整数:包括负数、正数和零。 那我会针对这两种形式,分别讲解它们的区别以及它们在内存中存储是否有差异。 首先我们得想一个问题:既然有了有符号整数,为何还要来一个无符号整数呢?这个问题就好像“既生瑜何生亮”。但是我想说的是,每一个事物的存在都有它的道理,那究竟是什么道理能把整数分成这两大部分呢?别急,听我分析! 历史角度:从计算机刚诞生之初,就是为了计数使用的,所以当时在内存中存储的无符号整数是比较流行的,而且电子部件的构造较为容易,无符号整数就流传到现在了。功能角度(重要):无符号整数有它相对应的场景,而且它所能表示最大正数的范围是有符号整数所能表示最大正数范围的两倍之多。也就是说,无符号整数在它相对应的场景下容错率比有符号整数要高。 这里你可能会想,为什么是两倍之多,而不是三倍、四倍呢? 其实这就要考虑到,无符号整数和有符号整数的二进制表示方式了。 假设是在32位的环境之下, 一个整型占4个字节,也就是32位。 对于无符号整数来讲,这32位都可以用来作为有效的数据位。数据所能表达范围:0~2的32次方-1; 对于有符号整数来讲,32位中的最高位要用做符号位(0表示"正",1表示"负"),其余的31位才为有效数据位。数据所能表示的范围:-2的31次方~2的31次方-1 到这里你就知道了为什么是两倍之多了。这里我们重点讲解有符号整数!!! 好了,回到正轨,我们继续讲原码、反码和补码(后面都是以有符号整数为例)。 敲黑板,重点来了: 原码:整数的二进制表示方式; 反码:如果该数为正数,原码和反码相同;如果该数为负数,反码就为除符号位不变,其余按位取反。 补码:反码 + 1 整型在内存中是补码的形式存储的。 接下来,我举几个例子,强化大家的意识: 在32位的环境下,分别写出88和-66的各自的原码、反码和补码。 88的原码:00000000 00000000 00000000 01011000 88的反码:00000000 00000000 00000000 01011000(正数的反码就是原码) 88的补码:00000000 00000000 00000000 01011001(反码+1) 88在内存中是这样的二进制串:00000000 00000000 00000000 01011001(补码) -66的原码:10000000 00000000 00000000 01000010

使用SQLite进行Python简单数据存储的线程安全解决方案

在 Python 中使用 SQLite 进行简单数据存储时,线程安全是一个需要注意的问题。SQLite 本身是线程安全的,但在多线程环境下,可能仍然需要做一些额外的工作来确保数据访问的安全性。 1、问题背景 一位开发者正在编写一个简单的聊天服务器和客户端,想要允许用户设置密码来保护他们的帐户。当用户想要启用密码保护时,他们可以通过发送 “/password ” 命令将帐户信息存储到 SQLite 数据库文件中,只有知道密码的用户才能使用该名称。 2、解决方案 由于 SQLite3 在 Python 中不是线程安全的,因此需要找到一种方法来安全地存储和管理数据。一种常见的解决方案是使用 multiprocessing.Manager() 模块,该模块提供了共享数据结构,可用于在不同的进程之间共享数据。 示例代码 import sqlite3 from multiprocessing import Manager # 创建一个共享管理器 manager = Manager() # 创建一个共享字典,用于存储用户帐户信息 user_accounts = manager.dict() # 在 SQLite 数据库文件中创建一个表 connection = sqlite3.connect('user_accounts.db') cursor = connection.cursor() cursor.execute('''CREATE TABLE IF NOT EXISTS user_accounts ( username TEXT PRIMARY KEY, password TEXT )''') connection.commit() # 将用户帐户信息存储到 SQLite 数据库文件中 def store_user_account(username, password): connection = sqlite3.

go语言的占位符

1、%v:值占位符,将值格式化为一个更紧凑的表示形式。 2、%+v:相比%v,如果是结构体,会带上字段名。 3、%#v:该值的go语法表示形式。 4、%T:值的类型的go语法表示。 5、%%:输出一个字面的百分号。 6、%t:单词 true 或 false。 7、%b:二进制表示形式。 8、%c:相应的Unicode码值。 9、%d:十进表示形式。 10、%o:八进表示形式。 11、%O:八进表示形式,带0o前缀。 12、%q:将值格式化为一个带有单引号的字符。 13、%x:将值格式化为一个不带符号的采用十六进制表示的字符。 14、%X:与 %x 不同的是将值格式化为大写字母形式。 15、%U:将值格式化为一个带有前缀 "U+"的字符串形式,Unicode格式。 16、%e:将值格式化为一个带小数点的科学计数法表示形式。 17、%E 将值格式化为一个带小数点的科学计数法表示形式。 18、%f:将值格式化为带小数点的浮点数表示形式。 19、%F:同 %f。 20、%g:将值格式化为一个合适的表示形式的字符串,可以自动选择带小数点的浮点数表示形式或不带小数点的浮点数表示形式。 21、%G:与 %g不同的是,%G会根据值的范围选择采用大写字母或小写字母表示的形式。 22、%s 字符串表示形式。 23、%p:将值格式化为一个指针的地址表示形式,十六进制表示,前缀 0x。 24、%.(数字)s:截取指定长度的字符串。 25、%w:将值格式化为一个错误消息的字符串形式。 1、%v:值占位符,将值格式化为一个更紧凑的表示形式。 package main import ( "fmt" ) type user struct { name string age int } func main() { u := user{name: "路多辛", age: 18} fmt.Printf("The value is: %v\n", u) m := map[string]interface{}{"name": "

SSE请求多种实现方式总结

SSE请求多种实现方式总结 什么是SSE一、怎么实现SSE请求(基础版本)1、前端实现:前端示例代码 2、 nodejs 后端示例代码3、特点 二、Fetch API实现SSE(升级版本)1、 node后端代码2、 前端Fecth请求实现3、特点 三、Fecth结合EventSource实现SSE(终极版本)1、node后端代码示例2、前端代码示例3、特点 四、总结 文前推荐一下👉 前端必备工具推荐网站(图床、API和ChatAI、智能AI简历、AI思维导图神器等实用工具): 站点入口:http://luckycola.com.cn/ 什么是SSE SSE(Server-Sent Events)是一种用于实现服务器主动向客户端推送数据的技术,也被称为“事件流”(Event Stream)。它基于 HTTP 协议,利用了其长连接特性,在客户端与服务器之间建立一条持久化连接,并通过这条连接实现服务器向客户端的实时数据推送。 SSE 和 Socket 区别 SSE(Server-Sent Events)和 WebSocket 都是实现服务器向客户端实时推送数据的技术,但它们在某些方面还是有一定的区别。 适用于场景 chatGPT 返回的数据 就是使用的SSE 技术 实时数据大屏 如果只是需要展示 实时的数据可以使用SSE技术 而不是非要使用webSocket 一、怎么实现SSE请求(基础版本) 1、前端实现: EventSource 对象是 HTML5 新增的一个客户端 API,用于通过服务器推送实时更新的数据和通知。在使用 EventSource 对象时,如果服务器没有正确地设置响应头信息(如:Content-Type: text/event-stream),可能会导致 EventSource 对象无法接收到服务器发送的数据。 前端示例代码 const sse = new EventSource('http://localhost:3000/api/sse' ) sse.addEventListener('open', (e) => { console.log(e.target) }) //对应后端nodejs自定义的事件名lol sse.addEventListener('lol', (e) => { console.log(e.data) }) 2、 nodejs 后端示例代码 import express from 'express'; const app = express(); app.

未设置辅助手机的谷歌账号停用,申诉回来后登录需要手机验证,验证两次后成功恢复。

谷歌账号被停用后怎么办?果断申诉,申诉方法和模板等见我前面的文章或视频。 通常申诉以后1-2天会反馈结果,而且大部分(80%以上)会第一次就被审批通过,如下图所示: 当收到上面这样的邮件,恭喜你!你被停用的谷歌账号已经可以恢复了,只需要登录、验证成功后即可。 那么被停用后的谷歌账号如何恢复呢? 根据GG账号服务的案例来看,只要点击登录,根据提示输入谷歌账号、密码、完成手机验证即可完整被停用谷歌账号的恢复——有的可以用原来绑定的辅助手机,有的得用其他地区好的手机。 今天这篇文章来分享一个案例,自己的谷歌账号没有设置辅助手机号,被停用以后根据我的模板进行了申诉,很快申诉获批了,然后登录验证的时候需要验证手机号,自己和朋友的国内手机号无法用于验证,找到我以后,连续验证两步成功完成恢复。 一、未设置辅助手机的谷歌账号停用后恢复的第1步验证 第一步验证是上面提示这个谷歌账号的地址,下面是输入手机号码的界面: PS.我在前面的文章中说过如果谷歌账号异常的时候出现上面是谷歌账号地址,下面是输入手机号码的框,可能无法恢复。但是根据实际案例来看,如果是账号被停用后恢复是有希望的。 二、未设置辅助手机的谷歌账号停用后恢复的第2步验证 在上面第一步验证通过(很多朋友会发现国内号码无法使用,这个时候可以考虑使用谷歌认可的号码)后,还需要第二次验证,界面是这样的: 这一步如果手机号码合适的话就可以完成账号的恢复,全程几分钟即可。 三、未设置辅助手机的谷歌账号停用后恢复的主界面 通常,在上面两次验证都顺利通过后,会进入到如下的界面。 到了这个界面,根据提示操作。 比如我昨天服务的这个朋友,在主页提示要添加辅助手机号码,点击蓝色按钮即可完成设置。 我个人建议的是:到了这个谷歌账号管理的后台,点击顶部的第四个标签:安全性(下图红圈处),然后根据提示设置或者确认辅助手机、辅助邮箱即可。 最后再回答经常问到的一个问题:谷歌账号有必要设置辅助手机吗,还是只设置辅助邮箱即可?根据我服务的案例来看,设置辅助手机的利大于弊,有的时候谷歌会把手机验证码作为优先级更高的验证方式,而且不设置辅助手机的账号并不比设置了辅助手机的账号出现的异常多。 另,谷歌账号的辅助手机可以使用国内手机号码,建议输入格式为 +86 11位手机号。一个国内手机号可以作为多个谷歌账号的辅助手机号码(通常认为3个左右都是可以接受的)。

数据结构之并查集

找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏:数据结构(Java版) 并查集相关概念 并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。比如说,我们可以用并查集来判断这两个人是否是亲戚(有没有最近公共祖先)或者两个人是否属于一个阵营等。 虽然并查集是一种树形结构,但是其底层的实现和堆一样是一个数组。这个数组的大小就代表了我们要处理的集合大小,而这个数组下标对应的值就是这个下标的根结点。如下所示: 通过上述图片我们可以知道一下几个结论: 1、查找元素属于哪个集合沿着数组表示树形关系以上一直找到根(即:树中中元素为负数的位置); 2、查看两个元素是否属于同一个集合沿着数组表示的树形关系往上一直找到树的根,如果根相同表明在同一个集合,否则不在; 3、将两个集合归并成一个集合,即将一个集合的根结点对应的值改为另一个集合的根结点即可; 在改动的时候要注意: (1):另一个集合被改的下标为未被改的集合的根结点 (2):未被改的集合的根结点的值要发生改变:加上另一个集合根结点的值。 4、集合的个数:遍历数组,数组中元素为负数的个数即为集合的个数。 模拟实现并查集 public class UnionFindSet { public int[] elem; // 将数组初始化为-1,证明每个元素刚开始都是一个独立的集合 public UnionFindSet() { elem = new int[10]; Arrays.fill(elem, -1); } public UnionFindSet(int n) { elem = new int[n]; Arrays.fill(elem, -1); } // 找到val对应的根结点 public int findRoot(int val) { // 注意val是数组的下标 // 得判断下标的合法性 if (val < 0) { throw new IndexOutOfBoundsException("数据下标不合法"); } // 只有当数组下标对应的值为负数时,才算找到了根节点 while (elem[val] >= 0) { val = elem[val]; } return val; } // 合并两个元素 public void union(int val1, int val2){ if (val1 < 0 || val2 < 0) { throw new IndexOutOfBoundsException("

ECMAScript 性能优化技巧与陷阱

ECMAScript 性能优化技巧与陷阱 在现代Web开发中,JavaScript(ECMAScript的实现)已成为构建高性能应用的核心语言。随着应用规模的扩大和复杂性的增加,性能优化变得尤为重要。本文将深入探讨ECMAScript性能优化的技巧与常见陷阱,帮助开发者在实际项目中提升代码性能。 一、理解性能瓶颈 在进行性能优化之前,首先需要了解性能瓶颈的来源。性能瓶颈通常可以分为以下几类: CPU瓶颈:代码执行速度慢,通常由于复杂的计算或循环导致。内存瓶颈:内存使用过高,可能导致垃圾回收频繁,影响性能。网络瓶颈:网络请求延迟或数据传输量过大,影响应用响应速度。DOM操作瓶颈:频繁的DOM操作会导致重排和重绘,影响页面性能。 通过性能分析工具(如Chrome DevTools)监测应用性能,可以帮助识别瓶颈所在。 二、性能优化技巧 1. 减少不必要的计算 在编写代码时,尽量避免重复计算。可以使用缓存技术来存储计算结果,减少不必要的计算开销。 const cache = {}; function expensiveCalculation(input) { if (cache[input]) { return cache[input]; } const result = /* 复杂计算 */; cache[input] = result; return result; } 2. 使用合适的数据结构 选择合适的数据结构可以显著提高性能。例如,使用Set和Map可以在查找和插入时提供更好的性能。 const uniqueItems = new Set(array); 3. 避免全局变量 全局变量会增加查找时间,尽量使用局部变量或模块化的方式来管理变量。 function example() { const localVar = 'I am local'; // 使用 localVar } 4. 优化循环 在循环中,避免在每次迭代中进行复杂的计算或DOM操作。可以将循环外的计算结果存储在变量中。 const length = array.length; for (let i = 0; i < length; i++) { // 处理 array[i] } 5.