目录
1.安装mysql数据库
首先添加mysql 的yum repo信息:
安装mysql:
启动mysql服务:
重置密码:
创建seata数据库: 创建表:
2.安装nacos
3.安装Seata:
1.解压seata压缩包:
2.修改配置文件:
3. 将seata配置数据导入到nacos配置中心
4. 启动seata:
5.Springboot中配置seata:
3. springboot配置:
1.父pom配置:springboot,springCloud版本管理
2.子pom配置:nacos版本配置: 4.参考文章:
实际上只是部署一个单例的Seata,但是仍然按照集群的方式去配置。Seata的高可用依赖于注册中心、配置中心和数据库来实现;因此我们需要修改相关的配置。下面我们以nacos(注册中心和配置中心)和MySQL为例子,Seata-Server使用注册中心进行集群间的通信,同时将事务数据保存到数据库中让整个集群统一使用事务信息。
关于nacos安装,请参考:centos7 部署nacos_wdquan19851029的专栏-CSDN博客
1.安装mysql数据库 本文使用yum安装
首先添加mysql 的yum repo信息: 这个根据你想要安装的mysql版本 rpm -ivh https://repo.mysql.com//mysql57-community-release-el7-11.noarch.rpm
安装mysql: yum install mysql-server -y --nogpgcheck
加 --nogpgcheck是为了解决这个错误:Public key for mysql-community-server-5.7.37-1.el7.x86_64.rpm is not installed
warning: /var/cache/yum/x86_64/7/mysql57-community/packages/mysql-community-common-5.7.37-1.el7.x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID 3a79bd29: NOKEY
Public key for mysql-community-common-5.7.37-1.el7.x86_64.rpm is not installed
(2/6): mysql-community-common-5.7.37-1.el7.x86_64.rpm | 311 kB 00:00:02 (3/6): mysql-community-libs-5.
题目 思路和解题方法 方案一——遍历+哈希表 仅能过60%样例,大多数同学都用的该方法,就不过多赘述
#include <iostream> #include <unordered_map> using namespace std; int main() { string s; cin >> s; int n = s.size(); int res = n; for (int i = 0; i < n; ++i) { unordered_map<char, int> m; ++m[s[i]]; for (int j = i + 1; j < n; ++j) { ++m[s[j]]; res += m.size(); } } cout << res; return 0; } 首先,代码声明了一些变量:
i、n 和 sum 是用于迭代、记录字符串长度和计算最终结果的变量,都被初始化为 0。a 是一个字符数组,用于存储输入的字符串,数组大小为 1000000。s 是一个长度为 26 的整型数组,用于记录每个小写字母最后一次出现的位置。 通过 cin 输入字符串到数组 a 中,并使用 strlen 函数获取字符串 a 的长度赋值给变量 n。
本文介绍的主要是跟腾讯云的连接。
一、ESP8266烧录固件 1、AT指令开发 就是把ESP8266当作一个WIFI模块来使用。使用AT指令开发离不开固件包,使用不同的物联网平台需要烧录不同的固件包,这里使用串口进行烧录。
2、硬件准备 由于腾讯云的固件包需要2M以上的flash,而ESP8266-01系列只有1M,所以只能使用ESP8266-12系列或者ESP8266-07系列。
3、软件准备 腾讯云AT固件下载地址 AT串口使用UART0,默认的Tx为GPIO1,Rx为GPIO3,但烧录了在官网下载的腾讯云固件之后,用于通信的串口会被修改为UART1,即GPIO13和GPIO15。安信可提供了两个版本,下载地址:https://axk.coding.net/s/296d525b-cd31-427e-9d4c-ec3dca5a3d43,一般选择1_3的版本。
MQTT透传AT固件下载地址 MQTT透传AT固件包
Flash烧录工具 flash下载工具
烧录界面:
二、腾讯云-物联网开发平台 IoT Explorer 1、新建产品与设备 物联网开发平台界面:点击产品控制台。
新建项目:
点击刚刚新建的项目,在项目下新建一个产品,各选项默认就行了。
点击新建的产品,直接来到设备调试页面,点击新建设备。
2、设备信息 点击新建好的设备,即可看到该设备的一系列信息,有三个有用的元素:产品ID、设备名称、设备密钥,称为三元素,ESP8266需要通过这三元素来连接到云端设备。
3、物模型 回到最开始的物模型页面,在这里可以为产品添加功能。
4、交互开发 配置完基本功能后,这一步需要为设备配置一个手机端的操作界面,这里需要切换到交互开发页面。
一般只需要配置前三个选项。
三、终端操作 可使用安信可提供的测试工具:IoTDev Tool
ESP8266需要使用到的指令: 1、连接WIFI AT+CWMODE=1:设置客户端模式AT+CWJAP=”WIFI名称”,”WIFI密码”:连接上WIFI 2、连接物联网设备 AT+TCDEVINFOSET=1,”产品ID”,”设备名称”,”设备密钥”:设置平台信息,三元素AT+TCMQTTCONN=1,5000,240,1,1:配置连接服务器参数AT+TCMQTTDISCONN:断开服务器连接 3、订阅主题 物联网平台的主题格式为**$thing/down/property/{ProductID}/{DeviceName},**其中ProductID是产品ID,DeviceName是设备名称。
AT+TCMQTTSUB=”主题”,0:订阅主题AT+TCMQTTUNSUB=”主题”:取消订阅主题 4、发布主题 物联网平台的主题格式为**$thing/up/property/{ProductID}/{DeviceName},**其中ProductID是产品ID,DeviceName是设备名称。
AT+TCMQTTPUB=”主题”,0,”数据”:发布主题 四、JSON数据处理 1、分离出Topic和JSON数据 腾讯云下发的数据打印之后的数据:
代码如下:
/*********************************************** * @brief : ESP8266分离出Topic和CJSON * @param : void * @return: sub_data:分离出来的数据的地址 * @date : 2023.11.17 * @author: L ************************************************/ uint8_t *Eep8266GetData(void) { char* sub_ptr = NULL; char* sub_data = NULL; uint8_t i = 0; sub_ptr = strstr((const char*)esp8266_buff,"
题目描述 UIM 在写程序的空闲玩一款 MOBA 游戏。
当敌方的小兵进入到我方防御塔的范围内,就会持续受到防御塔造成的伤害;当然我方英雄也可以对它造成伤害。当小兵的血量降到了 0 或者更低,就会被击杀。为了获得经验,UIM 希望在防御塔将这个小兵杀死之前,亲自补刀将其击杀。
为了简化问题,我们假设这个小兵有 ℎh 点的生命值。每次防御塔的攻击可以给小兵造成 x 点伤害,而你的英雄每次攻击可以给小兵造成 y 点伤害。你的攻击速度和防御塔攻击速度相同,所以你可以在防御塔第一次攻击小兵之前,或者每次防御塔攻击之后,选择是否对小兵进行一次攻击,当然你也可以选择不攻击。
现在想知道,给出这些信息,判断英雄是否有办法将这个小兵击杀?
输入格式 每个测试点由多组数据组成。
输入第一行,包含一个正整数 T,表示数据组数。
接下来 T 行,每行三个非负整数 h,x,y,其意义已经在题目描述中给出。
输出格式 输出 T 行。对于每组数据,如果可以最后将小兵击杀,输出 Yes,否则输出 No。
输入输出样例 输入 #1复制
5 100 100 1 100 97 1 100 98 1 100 99 1 100 100 0 输出 #1复制
No No Yes Yes No 说明/提示 数据的组数不多于 50,1≤ℎ≤10的18次方 1≤h≤10的18次方,0≤x,y≤10的18次方。
思路分析: 我们看题:
给定小兵生命,防御塔攻击 , 英雄攻击,求英雄是否有办法将这个小兵击杀。 于是我们得到以下结论:
若英雄攻击为 0 则是NO。
一、安装教程(如果是爬坑https<unknown>可以往下翻到底部)
1.官网下载了charles 选好盘符进行安装 安装后打开 界面如下
2.功能介绍
(1)清空所有请求
(2)开始/关闭抓取请求
(3)开启/关闭SSL代理
(4)开启/关闭限流
(5)开启/关闭断点
(6)编辑请求 并可执行
(7)重发请求
(8)验证请求
(9)购买许可证
(10)工具
(11)设置
3.开始配置
(1)点击Proxy->Proxy Setting...开启代理 设置端口号 点击ok
(2)打开手机,手机网络要和电脑连接相同网段 然后打开手机连接的wifi 进入到设置界面滑动到最下面 http代理 修改配置代理为手动 在调试完成后 记得将代理改为自动 不然影响上网功能
服务器地址写电脑的IPV4地址 可以用cmd ipconfig查 也可以用charles中的Help->Local IP Address查询到 示例:192.168.210.125
(3)设置抓取的地址 Proxy->Recording Settings在Include中设置抓取包含的域名 端口号等 我这里请求没写端口号 大家可以按需去写 Exclude中设置排除掉的地址
(4)设置SSLProxy Settings 针对https的请求 这个是一定要设置的 我这里只写了一个端口号443 也可以写https请求的地址和域名等 按需设置
(5)第一次通过手机访问发送请求时,Charles会弹出提示框,提示有设备尝试连接到Charles,是否允许,如果不允许的话,手机发送请求失败,点击Allow允许,这样这个设备的IP地址就会添加到允许列表中,如果错误点击了Deny可以重启Charles会再此提示,或者通过Proxy->Access Control Settings手动添加地址,如果不想每个设备连接Charles都要点击允许的话,可以添加0.0.0.0/0允许所有设备连接到Charles。这里第一行的IP地址是手机的IP地址 只要点击Allow之后 就会自动同步进Charles 不用手动输入
基础配置先配置这些
然后请求基本都是https的请求 我们需要到Help->SSL Proxying->Install Charles Root Certificate中去安装证书
点击安装证书,一直点击下一步
我这里选的是根据证书类型,自动选择证书存储 点击下一步 直到导入成功提示
这边给大家介绍一下,String中是如何删除指定字符,博主粗略总结了11种方法,如果有不足或者遗漏希望读者能够不吝赐教。
作者:CoderPLDQ
https://blog.csdn.net/li767517488/article/details/64919194
第一种方法
通过循环从前往后遍历,如果不是要删除的字符则加到处理后的字符串中,代码如下:
public String deleteCharString0(String sourceString, char chElemData) { String deleteString = ""; for (int i = 0; i < sourceString.length(); i++) { if (sourceString.charAt(i) != chElemData) { deleteString += sourceString.charAt(i); } } return deleteString; } 第二种方法
通过循环确定要删除字符的位置索引,然后通过分割字符串的形式,将子字符串拼接,注意最后一段子字符串和源字符串中没有要删除字符的情况,代码如下:
public String deleteCharString1(String sourceString, char chElemData) { String deleteString = ""; int iIndex = 0; for (int i = 0; i < sourceString.length(); i++) { if (sourceString.charAt(i) == chElemData) { if (i > 0) { deleteString += sourceString.
更多资料获取 📚 个人网站:ipengtao.com
地理编码和位置信息在现代应用中扮演着重要角色。geopy是一个强大的Python库,提供了处理地理编码、逆地理编码和地理距离计算的功能。本文将深入探讨如何使用geopy库处理位置信息,以及其在实际应用中的作用。
开始使用Geopy 首先,安装geopy库。通过pip,执行以下命令进行安装:
pip install geopy 导入geopy库并准备环境:
from geopy.geocoders import Nominatim from geopy.distance import geodesic geolocator = Nominatim(user_agent="geoapp") 地理编码与逆地理编码 地理编码是将地址转换为经纬度坐标的过程。逆地理编码则是根据坐标获取地址信息。
地理编码 使用geopy进行地理编码:
location = geolocator.geocode("北京天安门") print(f"北京天安门的经纬度坐标为: {location.latitude}, {location.longitude}") 逆地理编码 将坐标转换为地址信息:
location = geolocator.reverse("40.4168, -3.7038") print(f"坐标(40.4168, -3.7038)对应的地址为: {location.address}") 距离计算 geopy可以方便地计算两点之间的地理距离。
coord1 = (51.5074, 0.1278) coord2 = (48.8566, 2.3522) distance = geodesic(coord1, coord2).kilometers print(f"这两点之间的距离为 {distance} 千米.") 不同地理编码服务的应用 geopy支持多种地理编码服务,如Nominatim、Google Maps等。可以指定不同服务来获取地理信息。
from geopy.geocoders import GoogleV3 geolocator = GoogleV3(api_key='YOUR_API_KEY') location = geolocator.
目录
一、基本介绍
二、基本使用
2.1、package导入
2.2、同步请求
2.3、异步请求
2.4、post请求
2.5、post发送json信息
2.6、post发送文件信息
2.7、post发送多种请求信息
三、小结
一、基本介绍 在之前的Java网络编程(一)中已经介绍了网络编程里最基本的概念,即套接字socket。然而socket虽然基础,但使用起来颇为麻烦、复杂,因此在开发网络功能的过程中,一般会使用其它第三方库进行网络请求。而本文将要介绍的就是一个比较经典的Java网络请求库--OkHttp。
Java OkHttp是一个基于Java语言开发的开源库,可以用于HTTP和HTTP/2客户端请求。该库提供的API简单清晰,功能丰富,能够极大简化开发者请求HTTP时的操作,因此被广泛地应用于Android应用和java程序中。
二、基本使用 2.1、package导入 如果是Android的gradel项目,那么在build.gradle中添加以下依赖语句
implementation("com.squareup.okhttp3:okhttp:4.9.0") 如果是maven项目,那么在pom文件中添加以下依赖即可
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.9.0</version> </dependency> </dependencies> 想要最新版本或者下载本地jar包的可以去官网上找,地址如下
https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
2.2、同步请求 首先创建一个OkHttpClient,然后根据url构建最基本的request请求,再通过client对象和request对象来构造Call对象即可使用call对象的execute方法开始网络请求。
要注意的是,网络请求可能是一个耗时较长的过程,一般不允许在主线程中开启网络请求。而call对象的execute方法则是一个同步请求的方法,因此需要创建一个子线程来执行该方法,具体代码如下:
public void startGet() { String url = "https://wwww.baidu.com"; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(url).get().build(); final Call call = client.newCall(request); new Thread(new Runnable() { @Override public void run() { try { final Response response = call.
在前两个小节中我们实现了部门页面和员工页面的代码逻辑,其中对于数据库的使用我们都是在model.py 模块里面进行建立,接下来我将为大家介绍一种新的一种方式----ModelFrom。
ModelFrom介绍 ModelForm是Django中的一个表单类,它可以根据一个模型类自动生成对应的表单。使用ModelForm可以大大简化表单的创建和验证工作。
传统方式:
1、用户提交数据没有校验
2、页面没有错误提示
3、数据库字段很多的情况下,每个字段都要手写
4、关联数据,手动获取
ModelFrom可以充分的解决这些问题,下面我将重写员工页面的代码逻辑,带领大家引入其魅力。
将各组件方法进行分组归类: 我们之间在给各个组件方法代码进行编写的时候,都是在view.py里面进行编写的,这样做其实并不太好对于后期代码的维护,不方便程序员进行查阅,因此我们可以在我们app文件下创建一个views文件夹用于存放我们的各个组件方法。
在其中建立两个python文件,分别用于存放员工组件方法以及部门组件方法
在views.py文件中分别将这两个组件方法分别导入到上面两个py文件中。
在urls里面重新配置组件方法地址
原来的urls:
更改后的urls:
首先需要导入views文件夹,将其中的各个模块引入,最后只需要借用这些模块就可以调用各个组件的方法。
全部更改完成之后下面我们开始重写员工表的各组件方法。
员工信息添加-----ModelForm版本 我们在原来的员工信息中输入信息时我们可以发现,只要我们输入的和model模块里面建立字段保持一致,那我们就可以将这个信息添加进来,但是这样对于实际开发中是不可取的,因为对于部分字段我们需要添加一些约束。
例如我们添加一下信息:
我们可以发现这些信息是可以直接添加进来的,但是我们又希望里面会给我们提供一些约束,当不满足这些约束的时候信息是不能添加进来的,这个时候有小伙伴可能会想,我在做添加信息组件方法时我加入条件判断对我需要字段进行约束不就可以了吗。这样做的方法是可行的,但是不够好。对于字段比较多的时候,我们不能对每一个字段进行一个约束,这样会让我们的代码看上去冗余。因此我们接下来引入ModelFrom来进行这方法的重写。
创建UserModelForm类 class UserModelForm(forms.ModelForm): # 对于 name 字段进行重写 name = forms.CharField(min_length=2, label='姓名') # 硬性规定写法 class Meta: # 数据库的导入 model = models.UserInfo # __all__ 代表所有字段 fields = '__all__' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for title, field in self.fields.items(): field.widget.attrs = {'class': 'form-control'} 对于 name 字段:
我们可以从之前在model.py里面的name字段可以看出,之前我们规定的是最大字长为64,但是现在我们想要用户输入的姓名最少也得是2个字,因此我们在UserModelForm类里面对name字段进行一个重写。
对于 Meta类,我们在里面添加我们的数据库以及数据库里面的所有字段。
printf()的占位符有许多种类,与【C语言】的数据类型相对应。下面按字母排序,列出常用的占位符,方便查找。
%a:十六进制浮点数,字母输出为小写。 %A:十六进制浮点数,字母输出为大写。 %c:字符。 %d:十进制整数。 %e:使用科学计数法的浮点数,指数部分的e为小写。 %E:使用科学计数法的浮点数,指数部分的E为大写。 %i:整数,基本等同于%d。 %f:小数(包含 float 类型和 double类型) 。 %g:6个有效数字的浮点数。整数部分一旦超过6位,就会自动转为科学计数法,指数部分的e为小写。 %G:等同于%g,唯一的区别是指数部分的E为大写。 %hd:十进制 short int型。 %ho:八进制 short int型。 %hx:十六进制 short int类型。 %hu: unsigned short int型。 %ld:十进制 long int类型。 %lo:八进制 long int类型。 %lx:十六进制 long int类型。 %lu: unsigned long int。 %lld:十进制 long long int类型。 %llo:八进制 long long int类型。 %llx:十六进制 long long int型。 %llu: unsigned long long int型。 %Le:科学计数法表示的long double类型浮点。 %Lf: long double类型浮点。 %n:已输出的字符串数量。该占位符本身不输出,只将值存储在指定变量之中。 %0:八进制整数。 %p:指针。 %s:字符串。 %u:符(unsigned int)。 %x:十六进制整数。 %zd: size_t类型。 %%:输出一个百分号。 C语言常用的为:
4个组成部分 保留区域文件分配表区域 (File Partition Table,简称FAT)根目录区域数据区域 保留区域 保留区域的第一个扇区(sector)很重要。它的大小是512 byte,对这个扇区有多种叫法----启动扇区(boot sector),保留扇区(reserved sector),0号扇区(0th sector)等等,在DOS分区下,又被叫做操作系统引导记录区(DOS BOOT RECORD,简称DBR)。
表1 启动扇区定义 命名字节偏移字节长度功能描述BS_jmpBoot03跳转指令BS_OEMName38厂商标志与版本号BPB_BytsPerSec112每个扇区的字节数,该值只能是512,1024,2048,4096BPB_SecPerClus131每个簇的扇区数,合法值为1,2,4,8,16,32,64,128 。但必须保证(BPB_BytsPerSec*BPB_SecPerClus)<= 32KB。虽然有些操作系统支持64KB大小的簇,但很多应用安装程序无法在这样的FAT文件系统上正常运行BPB_RsvdSecCnt142保留区域的扇区数。该值一定不为0。BPB_NumFATs161FAT表的数量,通常为2。BPB_RootEntCnt172FAT32该值为0BPB_TotSec16192FAT32该值为0BPB_Media211媒体描述符BPB_FATSz16222FAT32该值为0BPB_SecPerTrk242每磁道扇区数。用于BIOS中断0x13,只对特殊形状的存储介质有效。BPB_NumHeads262磁头数。用于BIOS中断0x13,只对特殊形状的存储介质有效。BPB_HiddSec284隐藏扇区数。BPB_TotSec32324该分区总扇区数BPB_FATSz32364一张FAT表所占扇区数BPB_ExtFlags402BIT[3:0]:活跃FAT表编号。 BIT[6:4]:保留。 BIT[7]:0–>FAT表实时镜像到所有的FAT表;1–>只有一个FAT表活跃,即 BIT[3:0]所指的FAT表。BIT[15:8]:保留BPB_FSVer422FAT32的版本号BPB_RootClus444根目录的首簇簇号。通常是2。也可以是其它值。BPB_FSInfo482保留区域中FSINFO结构的扇区号,通常为1。BPB_BkBootSec502保留区域中备份引导扇区的扇区号,通常为6。BPB_Reserved5212保留,以后扩展使用,目前都置0.BS_DrvNum641驱动器号。BS_Reserved1651保留。置0。BS_BootSig661扩展引导标识(0x29),表示接下来的3个域是可用的。BS_VolID674卷序列号BS_VolLab7111卷标号BS_FilSysType828文件系统类型。为“FAT12 ”, “FAT16 ”, or “FAT ”三者之一。BS_BootCode90420启动代码BS_Signature0x555101有效标志,固定为0x55BS_Signature0xAA5111有效标志,固定为0xAA 注:BS(Boot Sector),BPB (BIOS Parameter Block)
文件分配表(FAT) FAT32文件系统中,每条FAT表项占用4 byte,但实际上最高4bit是保留位,未使用。由于有效bits只有28位,所以最大簇号为0xFFFFFFFF(268435455),boot sector规定簇最大为32KB,折算下来最大容量约为8TB。
FAT表项从0开始编号,0 号地址与 1 号地址被系统保留并存储特殊标志内容。从 2 号地址开始,每个地址对应于数据区的簇号, FAT 表中的地址编号与数据区中的簇号相同。
如果某个簇未被分配使用,它所对应的FAT表项内的FAT表项值即用 0 进行填充,表示该 FAT 表项所对应的簇未被分配。当某个簇已被分配使用时,则它对应的 FAT 表项内的 FAT 表项值也就是该文件的下一个存储位置的簇号。
FAT表代表的是一种链式关系。例如一个70KB大小的文件A,假定此时簇大小为32KB,则当前文件需占用3个簇。在目录项中,会记录文件A的各种信息,包括文件的首簇号、时间等等。当拿到首簇号后,查找该簇号的FAT条目,该条目记录的就是下一个存储簇号。假设文件A依次占用的是簇3、4、5。则在目录项中,记录的首簇号是3,而在FAT表中,簇3对应的FAT条目里面记录的是4,,簇4对应的FAT条目记录的则是5,而簇5对应的FAT条目记录的则是结束标志 0x0FFFFFFF。
根目录 根目录的簇号在boot sector中有记录,通常位于2号簇。
根目录在文件系统建立时即已被创建,其目的就是存储文件夹或文件的目录项。每个目录项的大小为 32 个字节。目录项中除记录文件夹或文件起始簇号外,还记录它的名字、大小(文件夹没有大小)、时间值等信息。
每个子目录(文件夹)或文件除具有一个短文件目录项外,还会有长文件名目录项。短文件名目录项固定占用 32 字节,长文件名目录项则根据需要占用 1 个或者若干个 32 字节。
数据区域 该区域存储文件内容。以簇为最小存储单位,即使文件大小不足1个簇,也会占用1个簇。每一个簇都有一个对应的FAT表项。
酒店管理系统
时代的发展带来了巨大的生活改变,很多事务从传统手工管理转变为自动管理。自动管理是利用科技的发展开发的新型管理系统,这类管理系统可以帮助人完成基本的繁琐的反复工作。酒店是出门的必需品,无论出差还是旅游都需要酒店的服务。由于在旺季预定酒店的人数太多,需要提前预定才不会影响行程。使用传统方式来管理酒店需要多人、多时间,开发酒店管理系统则可以有效的提高管理效率。
本酒店管理系统采用SpringBoot框架进行开发,数据库采用MySQL设计,运行环境为Idea。本系统包括前台界面、用户界面和管理员界面、员工界面。在前台界面里游客和用户可以浏览客房信息、公告信息等,用户可以预定客房,在用户中心界面里,用户可以管理预定信息,管理员负责用户预定的审核以及客房的发布、用户的入住等。员工也可以安排用户的入住以及管理客户的预定。本系统实现酒店客房的管理以及用户预定管理,以此来保证酒店的正常运行。
泛型的协变 父类对象可以引用子类
协变关键字out 逆变关键字in
消融实验:深度学习的关键分析工具 在深度学习和机器学习领域,消融实验(Ablation Study)是一种重要的实验方法,用于理解和评估模型的各个组成部分对其整体性能的贡献。通过这种方法,研究人员可以更深入地了解他们的模型,优化模型设计,以及验证特定功能或组件的有效性。让我们深入探讨消融实验的本质、重要性和应用方式。
消融实验的本质 定义 消融实验来源于医学术语,指的是切除或移除生物组织。在深度学习中,这个术语被借用来描述一个过程,即逐步移除或修改模型的某些部分(如层、节点、特征或参数),并观察这些改变对模型性能的影响。
目的 理解组件作用:识别哪些组件对模型性能至关重要。模型简化:确定是否可以去除某些部分而不显著影响性能,从而简化模型。验证假设:检验特定组件或特性的设计假设是否有效。 消融实验的重要性 模型透明度 提高模型的可解释性,帮助研究人员和开发者理解模型的工作原理。 性能优化 通过识别和去除不必要的部分,优化模型的性能和效率。 研究完整性 在发表研究结果时,提供消融实验可以增强研究的完整性和可信度。 实施消融实验 步骤 确定基线:首先确定模型的初始性能作为基线。逐步修改:移除或修改模型的一个组件。评估影响:评估这一改变对模型性能的影响。重复实验:重复这一过程,直到分析了所有关键组件。 注意事项 控制变量:每次只改变一个组件,以确保结果的准确性。综合评估:考虑不同指标对模型性能的影响,如准确率、执行时间等。 结论 消融实验是深度学习研究中的一个关键工具。它不仅帮助研究人员理解和优化他们的模型,还为科学发表提供了重要的验证手段。通过系统地分析模型的每个部分,消融实验让我们能够构建更有效、更可解释的机器学习模型。
0.下载地址
https://wwus.lanzouj.com/iOZUv1gkgpze 密码:123456
1.能进行单个和批量下载, 没有弄上传
2.速度奇差,可能是某些地方没弄好.有一定的进度显示,但是不太准.
3.很多地方没弄好,有能力的自己弄一下
4.在app.config文件配置sftp
1、问题描述
有以下一条Map结构的数据,sex字段的值是0
{ name:"test", sex:"0" } 对应的sex枚举
public enum SexEnum{ MAN("0"), WOMAN("1"); private String code; public SexEnum getByCode(String code) { for (SexEnumem : values()) { if (em.getCode().equals(code)) { return em; } } return null; } } 调用BeanUtil.toBean,map转bean,报Can not convert 0 to class SexEnum
2、排查过程
debug toBean方法,最终定位到cn.hutool.core.convert.impl包下的EnumConverter枚举转换类的tryConvertEnum方法,如下
/** * 尝试转换,转换规则为: * <ul> * <li>如果实现{@link EnumItem}接口,则调用fromInt或fromStr转换</li> * <li>找到类似转换的静态方法调用实现转换且优先使用</li> * <li>约定枚举类应该提供 valueOf(String) 和 valueOf(Integer)用于转换</li> * <li>oriInt /name 转换托底</li> * </ul> * * @param value 被转换的值 * @param enumClass enum类 * @return 对应的枚举值 */ protected static Enum tryConvertEnum(Object value, Class enumClass) { if (value == null) { return null; } // EnumItem实现转换 if (EnumItem.
题目 思路和解题方法 程序首先定义了一个函数check,用于判断一个字符是否为字母。接下来,程序读取输入的整数k和一行字符串str。定义了两个空的向量a和b,用于存储满足条件的子串的起始位置。使用for循环遍历字符串str的每个字符,检查是否存在以"Alice"和"Bob"开头的满足条件的子串,并将其起始位置记录在向量a和b中。初始化变量ans为0,用于记录满足条件的子串对数。使用双指针技巧遍历向量a中的元素(即以"Alice"开头的子串),维护一个窗口,窗口的左边界为l,右边界为r。在每次遍历时,通过移动右指针r和左指针l的位置,保证窗口内的子串满足要求。具体而言,右指针r向右移动直到超过以"Alice"开头的子串的末尾位置+k+5,左指针l向右移动直到超过以"Alice"开头的子串的起始位置-k-3。每次更新窗口后,将满足条件的子串对数加上窗口中的元素个数(即r-l),并累加到ans中。最后输出ans,即满足条件的子串对数。 复杂度 时间复杂度: O(n)
时间复杂度:假设输入的字符串长度为n,那么代码中的主要操作是遍历字符串、查找子串以及双指针移动。遍历字符串的时间复杂度为O(n),查找子串的时间复杂度为O(n),而双指针移动的时间复杂度为O(n)。因此,总体时间复杂度为O(n)。 空间复杂度 O(n)
空间复杂度:代码中使用了两个向量a和b,用于存储满足条件的子串的起始位置。最坏情况下,向量a和b的长度都可能达到n,因此它们所占用的空间复杂度为O(n)。此外,还有一些辅助变量和常数空间的占用,但相对来说是常数级别的。因此,总体空间复杂度为O(n)。
c++ 代码 #include<iostream> #include<vector> using namespace std; typedef long long ll; bool check(char c){ return c>='A'&&c<='Z'||c>='a'&&c<='z'; } int main(){ ll k; cin>>k; getchar(); string str; getline(cin,str); vector<ll> a,b; // 遍历字符串,找出Alice和Bob的位置 for(ll i = 0;i+3<str.size();i++) { // 判断是否为Alice if(str.substr(i,5) == "Alice" && (!check(str[i+5]))&&(!check(str[i-1])) && i+5<str.size()) a.push_back(i); // 判断是否为Bob if(str.substr(i,3) == "Bob" && (!check(str[i+3]))&&(!check(str[i-1]))) b.push_back(i); } ll ans =0 ; for(ll i = 0,l=0,r=0; i < a.
本文主要使用SAS模型进行时间序列数据的模型ARIMA模型的拟合和定阶
一、首先建立数据集,绘制时序图
data pp;
input a@@;
t= _n_;
cards;
0.97
0.45
1.61
1.26
1.37
1.43
1.32
1.23
0.84
0.89
1.18
1.33
1.21
0.98
0.91
0.61
1.23
0.97
1.1
0.74
0.8
0.81
0.8
0.6
0.59
0.63
0.87
0.36
0.81
0.91
0.77
0.96
0.93
0.95
0.65
0.98
0.7
0.86
1.32
0.88
0.68
0.78
1.25
0.79
1.19
0.69
0.92
0.86
0.86
0.85
0.9
0.54
0.32
1.4
1.14
0.69
0.91
0.68
0.57
0.94
最近博主也有创建springboot项目,发现了IntelliJ IDEA在通过Spring Initilizer初始化项目的时候已经没有java8版本的选项了。
基于这个问题,有了这篇文章的分享,希望能够帮助大家克服这个困难。
如图,现在创建springboot项目的时候,java版本只有17和21两个选项,刚好今天晚上有刷到关于这个问题的文章。
那么,难道idea就真的用不了java8了吗,很显然,答案是否定的。上面的界面点击Next,看到默认选择的springboot版本是3.2.0,点击finish。
过了一小会儿,项目就创建好了
打开pom.xml,修改parent版本和java.version的值
最后点击刷新maven,问题不就解决了,其实idea并限制不了我们用什么java版本,只是你在创建项目的时候就已经认为java8已经不可用。(虽然第一次的时候,我的第一反应也是这样ovo)。
好了,文章就分享到这里了,看完不要忘了点赞+收藏哦~
文章目录 01 简介02 安装03 自动创建模型类04 基础使用4.1 查询4.2 新增4.3 更新4.4 删除 05 事务 01 简介 在使用python开发的过程中,有时需要一些简单的数据库操作,而Peewee正是理想的选择,它是一个小巧而灵活的 Python ORM(对象关系映射)框架,用于简化数据库操作。
本文基于mysql数据库,介绍最基础和常用的用法。
官方文档:
https://docs.peewee-orm.com/en/latest/index.html
GitHub上目前已有10.5k Star:
https://github.com/coleifer/peewee
02 安装 # 安装peewee库 pip install peewee # 安装mysql数据库客户端 pip install pymysql 03 自动创建模型类 假设我有一个名为test的数据库,其中有一张名为user的表,此时可以通过命令自动创建该数据库下各个表的映射模型类:
python -m pwiz -e <db_type> -H <host> -p <port> -u <username> -P <db_name> > model.py 其中:
db_type:数据库类型,例如mysqlhost:数据库主机地址port:端口username:数据库连接的用户名db_name:数据库名称 示例:
python -m pwiz -e mysql -H 192.168.0.25 -p 3306 -u root -P test > model.
先参考 :
RTOS的任务触发底层逻辑
FreeRTOS的并行与并发思考-CSDN博客
AUTOSAR-OS的调度机制-调度表(没理解透,继续更新)
OSEK-任务调度机制-CSDN博客
OSEK与FreeRTOS在任务调度上最大的区别在于,FreeRTOS是基于全抢占任务调度和时间片轮转调度机制,具有并发和并行的能力。而OSEK主要以调度表机制和Alarm机制触发任务,不具备并行的能力。最大的相同点是都是根据优先级高低的全抢占调度机制(OSEK可选非全抢占)。
调度表: 调度表被称为任务控制块表(Task Control Block Table,TCB Table),它是一个静态定义的数组,用于存储系统中所有任务的信息。一个调度表被划分成多个到期点Expiry Points,每个到期点对应一个时间片,每张调度表中所有要执行的任务都放在一个静态数组里。当一个到期点到达时,调度器会检查该到期点对应数组里的就绪任务,之后根据任务的优先级进行全抢占任务调度。
每个任务在调度表中都有一个对应的任务控制块(TCB),包含了任务的相关信息,如任务的优先级、堆栈指针、状态等。调度表中的任务按照其优先级从高到低的顺序进行排列。优先级较高的任务的任务控制块位于调度表数组的较低索引位置,优先级较低的任务位于较高索引位置。 OSEK 中,任务切换不像 FreeRTOS 的就绪列表那样使用双向链表,而是通过遍历数组来选择下一个任务进行执行。OSEK中任务的优先级数值越小,优先级越高。
调度表中的任务按照任务的优先级放在一个静态数组里,要想区分在每个到期点执行什么任务,就要根据任务的状态信息来区分,每个到期点被执行的时候,会先将当前到期点将要执行的任务从原来的Suspended状态切换到Ready状态,这样一来,在调度器调度任务的时候,就只会执行Ready状态下的任务,之后再根据优先级高低进行任务的调度。
在OSEK的调度表机制中,调度表是一个静态数据结构,可以将调度表理解为固定时间片轮转调度,和FreeRTOS的时间片轮转调度机制相似,但又不同。
调度表中的到期点 Expiry Points 是通过调度表定义的系统时钟中断触发的,通过配置系统时钟中断的频率来控制到期点的触发频率。当系统时钟中断发生时,调度器会根据到期点的时间要求和任务的截止时间进行任务调度和切换。
OSEK和FreeRTOS在时间片轮转调度最大区别在于,FreeRTOS的时间片轮转调度机制是就绪列表中相同优先级任务根据滴答时钟触发的中断轮番获取CPU的控制权,而OSEK的调度表是基于调度表定义的每个到期点实现任务的切换,之后在每个到期点的时间片中,又按照全抢占调度机制调度任务。
除此之外,如果调度表中到期点前的任务没有执行完,到期点将要执行的任务优先级高于没有执行完的任务,则实施全抢占任务调度,没有执行完的任务会被堆栈保存上下文,在下一个任务周期执行完上次没有执行完的部分。
如果调度表中到期点将要执行的任务优先级低于还未执行完的任务,那么调度器会继续执行当前正在执行的任务。所以,在开发过程中就要注意如果遇到调度表中到期点将要执行的任务优先级低于还未执行完的任务,要在未执行完的任务最后面加一个 TerminateTask 的函数,这个函数可以执行切换任务的动作。
Alarm: 如果说调度表是基于时钟触发的中断,之后利用调度器执行和切换任务。Alarm是基于时钟触发的事件,之后利用调度器在特定的时间点触发与之关联的任务。
Alarm是一种定时机制,也就是在特定的时间点触发与之关联的任务的执行,他与FreeRTOS的全抢占调度的区别在于,FreeRTOS的全抢占调度是没有时间概念的,只要有高优先级来,那就去抢,任务的触发不会遵循一种时间精度上的调度,而Alarm是可以精确时间周期的触发任务,虽然任务之间是全抢占,但当高优先级任务执行完,会切回到没有执行完的任务。
而Alarm与调度表的区别在于,首先调度表是一种静态的任务调度方式,在调度表中,每个任务都被分配了一个固定的时间片来执行,如果你没有执行完,并且任务优先级低,很抱歉,等下一次轮到你再说吧。
Alarm触发的任务是直接由外部事件驱动的,可以理解为FreeRTOS中全抢占调度任务,对任务的抢占能力极强,对于任务的优先级要求比较高。而调度表是由一个固定的时间片触发调度器控制的,类似于时间片轮转调度,抢占能力比较弱,要求的是你只要在固定的时间执行了这个功能就可以了,即便没有执行完,下一个周期执行也可以,对于任务的优先级要求不需要很高。
在 Rte_Start 开启时,启用alarm,
在Rte_Stop时,停止alarm
调度表中如果时间没有到到期点,任务就执行完成,剩下的时间执行空闲任务,
麒麟v10系统arm64架构openssh9.5p1安装 制作openssh说明准备文件制作命令过程更新ssh过程 制作openssh 说明 理论上制作的多个rpm在arm64架构(aarch64)都适用
系统信息:4.19.90-17.ky10.aarch64 GNU/Linux
升级前备份好文件/etc/ssh、/etc/pam.d等以及开启telnet
升级后确认正常后关闭telnet。
备注:
原版本:OpenSSH_7.8p1, OpenSSL 1.1.1d 10 Sep 2019
执行yum update -y后,版本为OpenSSH_8.2p1, OpenSSL 1.1.1f
所以制作的版本ssh显示的openssl为1.1.1f,如果非这个版本的openssl,也可以安装,根据经验仅影响ssh -V的版本显示。因为没有更新openssl,实际的openssl version查看的还是原来的openssl版本。
准备文件 x11-ssh-askpass-1.2.4.1.tar.gz
openssh-9.5p1.tar.gz
制作命令过程 yum install rpm-build zlib-devel openssl-devel gcc perl-devel pam-devel xmkmf libXt-devel gtk2-devel make -y cp x11-ssh-askpass-1.2.4.1.tar.gz openssh-9.5p1.tar.gz /root/rpmbuild/SOURCES #只解压 openssh.spec到 /root/rpmbuild/SPECS目录 cd /root/rpmbuild/SPECS tar -xzvf ../SOURCES/openssh-9.5p1.tar.gz openssh-9.5p1/contrib/redhat/openssh.spec --strip-components=3 #修改openssh.spec配置文件 sed -i -e "s/%global no_gnome_askpass 0/%global no_gnome_askpass 1/g" openssh.spec sed -i -e "s/%global no_x11_askpass 0/%global no_x11_askpass 1/g"
FlowField流场寻路,利用网格存储每个点对目标点的推力,网格上的单位根据对于推力进行移动。用于大量单位进行寻路对于同一目的地的寻路,常用于rts游戏等。
对应一张网格地图(图中黑块是不可行走区域)
生成热度图 计算所有网格对于目标点(图中红点)网格的路径距离。(每个格子的移动距离算作1)。
通过dijkstra算法遍历出每个格子的路径距离.(a *算法启发函数结果为0就是dijkstra算法。之前NavMesh寻路有说明过a *算法)
void FlowFieldScene::createHeadMap() { unordered_map<int, float> openList; unordered_map<int, float> closeList; _distNode->removeAllChildren(); _dist.clear(); //FlowFieldMathHelper::mapHeight 地图高度,即地图在y轴上的格子数 for (int i = 0; i <= FlowFieldMathHelper::mapHeight; i++) { vector<float> d; d.resize(FlowFieldMathHelper::mapWidth + 1, 0); _dist.push_back(d); } //转换实际位置到网格坐标的位置 Vec2 gridPos = FlowFieldMathHelper::getGridPos(_touchBeganPosition); //每个网格都有个唯一id int gridId = FlowFieldMathHelper::getGridIdByGridPos(gridPos.x, gridPos.y); openList.emplace(gridId, 0); while (!openList.empty()) { pair<int, float> node = *openList.begin(); for (auto n : openList) { if (node.second > n.second) node = n; } openList.
废话少说,直接上代码,别的标签都不用管,只需修改 mirrors 标签之中的东西
<mirrors> <!-- 阿里镜像 --> <mirror> <id>alimaven</id> <mirrorOf>central</mirrorOf> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> </mirror> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> <mirror> <id>central</id> <name>Maven Repository Switchboard</name> <url>http://repo1.maven.org/maven2/</url> <mirrorOf>central</mirrorOf> </mirror> <mirror> <id>repo2</id> <mirrorOf>central</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://repo2.maven.org/maven2/</url> </mirror> <mirror> <id>ibiblio</id> <mirrorOf>central</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://mirrors.ibiblio.org/pub/mirrors/maven2/</url> </mirror> <mirror> <id>jboss-public-repository-group</id> <mirrorOf>central</mirrorOf> <name>JBoss Public Repository Group</name> <url>http://repository.jboss.org/nexus/content/groups/public</url> </mirror> <mirror> <id>google-maven-central</id> <name>Google Maven Central</name> <url>https://maven-central.storage.googleapis.com </url> <mirrorOf>central</mirrorOf> </mirror> <!
数仓架构(即席查询) 总体来说,Hadoop架构在数据量较低的情况下,运行速度远不及MPP架构,但数据量一旦超过某个量级,Hadoop架构在吞吐量方面将非常有优势。有些大数据数据仓库产品也采用混合架构,以融合两者的优点,例如Impala、Presto等都是基于HDFS的MPP分析引擎,仅利用HDFS实现分区容错性,放弃MapReduce计算模型,在面向OLAP场景时可实现更好的性能,降低延迟。
MPP vs Hadoop架构 - 知乎
ClickHouse进行轻量化数仓搭建【计算引擎:Hive VS ClickHouse】 ClickHouse适合简单的DW之上的即席查询。而Spark由于其分布式特性,导致其任务启动时间很长,因此不适合实现即席查询,但是对于大数据量的join等复杂查询时具备非常大的优势。
ClickHouse的优化重点在如何提高单机的处理能力,而Spark的优化重点在于如何提高分布式的协作效率。
ClickHouse与Hive的区别,终于有人讲明白了-clickhouse与hive 区别
impala刷新invalidate metadata VS refresh invalidate metadata的特点就是异步性和全量性。invalidate metadata比起refresh而言要重量级得多,并且它造成impalad之间查询不一致也会更严重。因此,也几乎禁止使用不带表名的invalidate metadata语句。
refresh的特点是同步性和增量性。并且,它的执行是围绕单表以及单表的分区进行的,因此它更轻量级,也更适合分区元数据或数据文件更改之后的刷新。
正确使用Impala的invalidate metadata与refresh语句-CSDN博客
查看HDFS路径命令 查询报错:该分区文件或目录不存在
hdfs dfs -ls hdfs://nameservice1/user/hive/warehouse/adl.db/a_gq_workdat_stat/
什么场景需要使用NiFi从Kafka中获取实时数据? 以下是一些可能需要使用NiFi从Kafka中获取实时数据的场景:
1.数据集成:如果你有一个Kafka集群作为数据源,希望将实时数据集成到其他系统或数据库中,可以使用NiFi来接收Kafka中的数据,并根据需要将其转换为不同的格式或协议,然后将其发送到目标系统中。
2.数据处理和分析:如果你需要对实时数据进行处理、转换、清洗、分析等操作,可以使用NiFi来接收Kafka中的数据,并利用NiFi的各种处理器和操作符来实现这些处理任务。例如,可以使用NiFi的JSON解析器来解析JSON格式的数据,然后将其转换为不同的格式或进行其他处理。
3.数据监控和报警:如果你需要实时监控数据的变化,并在某些情况下触发报警或通知,可以使用NiFi来接收Kafka中的数据,并使用NiFi的各种处理器和操作符来实现数据监控和报警功能。例如,可以使用NiFi的条件表达式来检查数据是否符合某个特定条件,并触发报警或通知操作。
4.数据流管理:如果你需要对数据流进行管理和控制,例如对数据进行过滤、路由、聚合等操作,可以使用NiFi来实现这些功能。NiFi提供了各种处理器和操作符,可以方便地对数据进行处理和管理。
总之,如果你需要将实时数据从一个系统传输到另一个系统,或者需要对实时数据进行处理、分析、监控等操作,可以考虑使用NiFi来实现这些功能。
实时数据可以由kafka直接输入数据服务api? 实时数据可以通过Kafka直接输入到数据服务API。
Kafka是一种分布式流处理平台,可以用于构建实时数据管道和流应用程序。它可以接受来自不同数据源的实时数据,并将其传输到不同的目标系统中。Kafka提供了一种高吞吐量、可扩展、可靠的方式,将数据从一个端点传输到另一个端点。
当实时数据通过Kafka输入到数据服务API时,Kafka将作为数据传输的中间件,将数据从源头发送到目标系统。数据服务API可以是一个独立的服务或者一个数据处理平台,用于接收Kafka传输的数据、处理数据、并将结果反馈回Kafka或其他目标系统。
例如,数据服务API可以使用一些常见的数据处理和机器学习框架(如Apache Flink、Apache Spark、TensorFlow等)来处理接收到的实时数据。这些框架可以对数据进行清洗、转换、分析、挖掘等操作,将处理后的数据用于业务决策、预警预测等应用中。
总之,通过Kafka直接输入实时数据到数据服务API是一种常见的实践,可以帮助企业快速构建高效、可靠的实时数据分析应用。
实时数据由Kafka传入数据服务API的中间,什么时候需要加入TDengine? Kafka-Nifi/CDC-TDengine-数据服务API
在实时数据分析中,可以在以下情况下考虑加入TDengine:
数据存储和查询:当实时数据量较大,需要高效地进行数据存储和查询时,可以将TDengine作为存储和查询引擎。TDengine针对时序数据进行了优化,能够高效地存储和处理大量数据,并提供了高效的查询功能。通过将实时数据存储在TDengine中,用户可以快速获取和分析这些数据。
数据处理和计算:当需要实时对大量数据进行处理和计算时,可以在TDengine中加入数据处理和计算逻辑。TDengine支持多线程、分布式查询,可以快速处理高并发的数据读取请求,从而满足实时数据处理的需求。
高可用性和稳定性:当实时数据分析系统需要高可用性和稳定性时,可以将TDengine作为高可用性的存储和查询引擎。TDengine采用了主从复制和自动故障转移机制,保证了系统的高可用性。当部分组件发生故障时,整个系统仍能正常运行,从而提供了稳定可靠的服务。
日志分析:当需要处理海量的日志数据,通过实时分析和挖掘日志数据,发现潜在的问题和优化点时,可以将TDengine作为日志分析引擎。TDengine可以用于实时监控系统的运行状态和性能指标,可以在系统出现故障或性能下降时,快速发现和解决问题。
总之,在实时数据分析中,根据具体需求和场景,可以在不同的环节中加入TDengine,以提供更高效、可靠、稳定的数据存储、查询、处理、监控等功能。
spark streming和flink,storm的区别 Spark Streaming、Flink和Storm都是流处理框架,但它们之间有一些区别。
Spark Streaming是一个批处理框架,它将数据流切分成细粒度的batch进行处理。它支持容错和批处理,但是它不支持低延迟和Exactly-once保证。 Flink同时支持流处理和批处理。一条数据被处理完以后,序列化到缓存后,以固定的缓存块为单位进行网络数据传输,缓存块设为0为流处理,缓存块设为较大值为批处理。Flink在低延迟和数据顺序方面(利用水印)等都相对Spark Streaming更具优势。 Storm只支持流处理任务,数据是一条一条的源源不断地处理。而MapReduce、Spark只支持批处理任务。
Spark和MR,谁处理的数据量更大? Spark和MR都是分布式计算框架,但是它们的处理数据的能力有所不同。一般来说,Spark处理数据的能力是MR的十倍以上 。Spark基于内存,而MR基于磁盘(HDFS) 。此外,Spark中除了基于内存计算外,还有DAG有向无环图来切分任务的执行先后顺序。而MR中只有map、reduce和join。
因此,如果你需要处理大量数据,那么Spark可能是更好的选择。但是如果你需要处理的数据量较小,则MR可能更适合你的需求。
Spark Standalone和YARN的区别如下 Yarn模式只需要一个节点,然后提交作业即可,不需要启动Spark集群的(不需要启动Master和Worker)。 Standalone模式需要在Spark集群上的每个节点都需要部署Spark,然后需要启动Spark集群(需要Master和Worker进程节点)。
目录 问题出现场景适用场景解决方式 问题出现场景 因为接口请求过慢,会出现改变请求参数重新调用接口后,数据被前一次的请求结果覆盖: 举例: 输入框变化时请求数据,输入框输入 search 接口请求顺序: 接口请求1:参数s 接口请求2:参数se 接口请求3:参数sea ... 但是由于接口的快慢不同,先请求的接口可能时间更长,所以接口返回结果的顺序可能为: 接口2 接口3 接口1 接口最后获取的结果就不准确了 适用场景 input框输入 select框选择 tab切换 路由切换 ...... 解决方式 使用**switchMap**和**takeUntil**实现接口防抖操作。 实现效果为:多次请求时切断上一次请求,保留最新一次请求。 具体代码如下: import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { apiService} from './../test.service'; import { Subject } from 'rxjs'; import { switchMap, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-testComponent', templateUrl: './testComponent.component.html', styleUrls: ['./testComponent.component.less'] }) export class testComponent implements OnInit, OnChanges { searchTrigger$ = new Subject(); unsubscribe$ = new Subject(); constructor( private api: apiService, ) { } ngOnInit(): void { // 获取数据 this.
BEVFusion简介、环境配置与安装以及遇到的各种报错处理 BEVFusion简介BEVFusion环境配置与安装报错解决 BEVFusion简介 针对点云投射到图像的多模态融合和图像投射到点云的多模态融合,前者会损失空间几何信息,后者会损失图像语义信息,这两种point-level的多模态融合方法均无法同时很好地处理目标检测和地图分割问题。
BEVFusion 是一种高效且通用的多任务多传感器融合框架。 它将多模态特征统一在共享鸟瞰图(BEV)表示空间中,在BEV空间下融合图像和点云特征,此网络是一个全卷积网络组成,并对2D-3D的视图转换作了效率优化与提升,将延迟减少了 40 倍以上,计算速度大大提高。
BEVFusion的网络结构如下图所示: BEVFusion环境配置与安装 博主自己的硬件配置如下:
Linux(Ubuntu 20.04)NVIDIA GeForce RTX 3090NVIDIA显卡驱动版本:12.0CUDA version:11.3 配置BEVFusion所需的python环境(若CUDA版本不一样,安装时需要做一些修改):
# 创建名为bevfusion的conda环境 conda create -n bevfusion python=3.8 -y conda activate bevfusion # 安装pytorch conda install pytorch==1.10.0 torchvision==0.11.0 torchaudio==0.10.0 cudatoolkit=11.3 -c pytorch -c conda-forge # 安装mmcv pip install mmcv-full==1.4.0 -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.10.0/index.html # 安装mmdetection pip install mmdet==2.20.0 # 安装nuscenes数据集工具、软件开发包 pip install nuscenes-dev-kit # 安装mpi4py pip install mpi4py==3.0.3 # 安装torchpack pip install torchpack # 安装numba pip install numba cd bevfusion # 编译、安装mmdetection3d python setup.
系列文章目录
一、 Python PyQt5简介二、QtWidgets主要子类:QWidget | QMainWindow | QDialog 代码举例解释,快速了解 文章目录 前言一、PyQt是什么?二、PyQt5安装三、PyQt5程序基本结构1、PyQt5:QtCore、QtGui、QtWidgets2、示例程序 总结 前言 本篇文章适合想要学习PyQt5的且为初学者人群(但必须会python的基本语法),我会为大家介绍使用 pyqt 编写的 gui 程序的基本结构,旨在帮助初学者能快速地理清如何使用pyqt
环境:
windows11python3pyqt5(已经有pyqt6了,但由于pyqt5还是用得挺多的) 一、PyQt是什么? 简单地说,PyQt = Python + Qt。
python:一门热门的编程语言,既然能看到这篇文章,肯定都会。
Qt:Qt是一个跨平台的C++开发库,主要用来开发图形用户界面(Graphical User Interface,GUI)程序,就是一个用c++编写的gui库,里面都是一些能让计算机 显示出特定图形的和管理这些图形 的代码
PyQt:由于c++学习难度相对较大,用起来有些难受,所以有人就想用能不能简单一点的python来使用qt这个图形库,让开发更有效率。简单地说就是用python使用由c++编写的qt。而PyQt5就是第五个大版本。
二、PyQt5安装 pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple # 使用清华大学的镜像 三、PyQt5程序基本结构 1、PyQt5:QtCore、QtGui、QtWidgets 我们先了解一下pyqt5的三个用的 最多的大模块(因为它还有很多个大的模块)
QtCore
QtCore 是PyQt5下面的一个模块,QtCore模块涵盖了包的核心的非GUI功能,此模块被用于处理程序中涉及到的 time、文件、目录、数据类型、文本流、链接、mime、线程或进程等对象。这部分和我们常见的普通的python的功能挺像的,但是还是有点不同
比如:QFile(qt的文件)、QTimer(qt的计数器)QtGui
QtGui 是PyQt5下面的一个模块,QtGui模块涵盖多种基本图形功能的类; 包括但不限于:窗口集、事件处理、2D图形、基本的图像和界面 和字体文本。
比如 font = QFont(),一个字体对象QtWidgets
在Qt中,生成窗口有三种方式: QWidget | QMainWindow | QDialog (以上都是QtWidgets的子类)页面的主窗口,一般看成一个容器,一个用来作画的画布。 2、示例程序 import sys # from PyQt5.
第一题:字符串拼接 键盘输入两个字符串,将这两个字符串进行拼接后输出。
输入描述:
键盘输入两个字符串 输出描述:
输出两个字符串拼接后的结果 示例1
输入
hello nihao 输出
hellonihao 思路:
可以用vector来存,逐个输出
ac代码:
#include<bits/stdc++.h> using namespace std; vector<string> st; int main() { int n; cin>>n; while(n--) { string str; cin>>str; st.push_back(str); } for(auto t:st)cout<<t; return 0; } 第二题:最小差值 问题描述
给定 n个数,请找出其中相差(差的绝对值)最小的两个数,输出它们的差值的绝对值。
输入格式
输入第一行包含一个整数 n。
第二行包含 n个正整数,相邻整数之间使用一个空格分隔。
输出格式
输出一个整数,表示答案。
样例输入
5
1 5 4 8 20
样例输出
1
样例说明
相差最小的两个数是5和4,它们之间的差值是1。
样例输入
5
9 3 6 1 3
样例输出
项目使用技术:uniapp + vue3 + vite4.0.3 + node(v16.20.0)
"@dcloudio/uni-app": "3.0.0-alpha-3081220230731001",
"@dcloudio/uni-mp-weixin": "3.0.0-alpha-3081220230731001",
"vue": "^3.3.4",
"vite": "4.0.3",
"engines": {
"node": ">=16.20.0",
"pnpm": ">=8.0.0"
},
最新测试:使用高版本node(v18.15.0), 删除node_modules依赖,重新安装,以下2个问题都可以解决了都不报错了。
一、vscode编辑器:终端打包微信小程序 复现步骤:在vscode终端中运行:pnpm build:mp-weixin-prod 命令,打包小程序生产包时,报错failed to load xxx/vite.config.ts,但实际项目根目录中有该vite.config.ts文件。
vscode端使用的node版本是:v16.20.0
最后解决:使用node版本(16.20.0)+ 若有@esbuild包,删除即可。
具体解决:之前忘了什么原因,手动在node_modules包下面放入了darwin-x64文件夹 =》 将node_modules下面的@esbuild文件夹整个删除即可。
摘自其他人图:我的报错项目只有darwin-x64文件夹,没有darwin-arm64文件 二、HbuilderX编辑器:点击发行-》 原生app-制作应用wgt包 复现背景: node_modules中也没有@esbuild目录 -》点击发行,终端提示报错:can't find xx/xx/vite.config.ts, 当前使用的node是v16.20.0。
最后解决:使用node版本(v18.15.0)+ 重新安装所有依赖。
具体解决:删除node_modules包 -》 切换node版本为v18.15.0, 重新安装依赖 pnpm install 即可。 参考链接: [报bug] Host version "0.17.19" does not match binary version "0.16.17" - DCloud问答 -- 这个报错是因为@esbuild文件中有2个包,darwin-x64和darwin-arm64,这2个包版本有0.
目录 一、前言二、kkFileView介绍三、kkFileView安装四、kkFileView的配置和使用 一、前言 网页端一般会遇到各种文件,比如:txt、doc、docx、pdf、xml、xls、xlsx、ppt、pptx、zip、png、jpg等等。
有时候我们不想要把文件下载下来,而是想在线打开文件预览 ,这个时候如果每一种格式都需要我们去写代码造轮子去实现预览功能就太复杂了,并且自己实现的话会有很多兼容性问题。
这个时候 kkFileView 的出现就解决了我们的问题。
二、kkFileView介绍 kkFileView 为文件文档在线预览解决方案,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等
kkFileView 官网
kkFileView 码云地址官网
kkFileView github地址官网
三、kkFileView安装 自 v4.1.0 版本开始 kkFileView 不再免费提供 Windows 和 Linux 的发行安装包了,以前旧版本的安装包也取消了下载入口,要下载安装包需要自己通过源码编译打包,或者可以花 99 块钱进那个 KK开源社区群获取。
如果你想自己通过源码编译打包最新的安装包,可以参考我另一篇文章:kkFileView 从源码编译最新安装包
不过我之前官网下载过 v4.0.0 版,也够用了,为了方便大家我已经上传百度云了,你可以通过下面文章中的链接进行下载,本文的安装使用教程也是基于 v4.0.0 版本进行操作 。
部署指南参考kkFileView - 在线文件预览 下面介绍Windows、Linux、docker三种安装方式。
1.下载Windows或Linux的 v4.0.0 安装包 :
1.1 windows安装包下载 (链接:https://pan.baidu.com/s/1hZCP5jcD5cKd-xCsMHfYxg 提取码:7uwd)
1.2 linux安装包下载 (链接:https://pan.baidu.com/s/1grhyoIQ_Tr2NHyCZPFYDWg 提取码:13hj)
2.Windows上安装:
2.1 下载的 zip 压缩包解压后进入 bin 目录,双击 startup.bat 启动 kkFileView
2.2 30秒后进入 log 目录查看 kkFileView.
gradient
求解梯度。
示例
FX = gradient(F) 返回向量 F 的一维数值梯度。输出 FX 对应于 ∂F/∂x,即 x(水平)方向上的差分。点之间的间距假定为 1。
使用方法:
x = -2:0.2:2;
y = x’;
z = x .* exp(-x.^2 - y.^2);
[px,py] = gradient(z);
在相同图窗中绘制等高线和向量。
figure
contour(x,y,z)
hold on
quiver(x,y,px,py)
hold off
diff
diff(X) , 求函数X的一阶导数;
diff(X, n) , 求函数X的n阶导 (n是具体整数);
diff(X,变量名), 求函数X的偏导数(对谁求偏导数,变量名就是谁)
diff(X, 变量名,n) ,求函数X的n阶偏导数。
syms x
y=sin(x)+cos(2x)
dy=diff(y)
利用diff函数求解数值函数的导数
例子2
X = [0 5 15 30 50 75 105];
Y1= diff(X,2) 对x求2阶导数
首先将 MultipartFile 文件转为byte[]数组形式,可以参考以下方法
private byte[] convertToByteArray(MultipartFile file) throws IOException { InputStream inputStream = null; try { inputStream = file.getInputStream(); byte[] bytes = new byte[inputStream.available()]; inputStream.read(bytes); return bytes; } finally { if (inputStream != null) { inputStream.close(); } } } 然后使用java.util自带的Base64工具即可转换
@Override public String updateUserAvatar(MultipartFile file) { //将file文件转为Base64 byte[] bytes = new byte[0]; try { bytes = this.convertToByteArray(file); } catch (IOException e) { return ""; } String avatar = Base64.getEncoder().encodeToString(bytes); return avatar; }
使用表单收集数据时,点击提交后检验必填项是否为空是一个很重要的功能,当使用了elementUI后这个问题就变的很简单了。对于简单的事情也是需要学习一遍才能掌握运用,在这里我将会用直白明了的话来为大家讲解"使用elementUI中表单组件时检验是否为空的功能"的详细运用。
以el-input为例(为了方便查看,多余的属性一律没写):
<template> //属性model是必须的,值记为A,属性rules的值为检验规则。 <el-form :model="formData" :rules="rules"> //属性prop是必须的,值记为B <el-form-item prop="age"> //属性v-model的值必须是A.B <el-input v-model="formData.age"> </el-form-item> </el-form> </template> <script setup> const rules = reactive({ //该属性名必须是要检测的属性值B age:[{required: true, message: "年龄不能为空", trigger: "blur"}] }) </script> 在上述代码的template中,el-form 包裹了 el-form-item,el-form-item 包裹了 el-date-picker 并设置了相应的验证规则。通过 :rules 属性,我们定义了 age必须为非空。
在script中定义rules的检验方法:其中
"required"是HTML表单元素中的一个属性,也可以在一些前端框架(如Vue.js)的表单验证规则中使用。它指示表单元素必须填写值,否则提交表单时会触发验证错误;
"message"属性用于指定在验证失败时显示的错误消息。这个消息将被显示给用户,以便他们了解为什么表单验证失败;
"trigger"是表单验证规则中的一个属性,用于指定触发验证的事件。它告诉验证器在什么时候开始验证表单项,与"blur"一块使用表示当失去焦点时触发检验。
SG-8200CG和SG-8201CG (sg -8201系列)利用爱普生新的低噪声分n锁相环技术,与上一代爱普生可编程晶体振荡器相比,稳定性提高了约2x,相位抖动降低了<1/25。sg -8201系列可编程为1.2MHz至170MHz的任何频率,工作温度范围可达+125°C。sg -8201系列是各种消费和工业应用的理想选择,这些应用需要小尺寸和/或在恶劣环境中操作。这种可编程SPXO可用于小批量和快速周转时间,适用于1.2 MHz至170 MHz范围内的任何频率,有助于从开发到批量生产的汽车应用。
功能 -尺寸:2.5 x 2.0 x 0.74 mm—频率范围:1.2 MHz ~ 170 MHz—VCC (Supply voltage): 1.62 V ~ 3.63 V—ICC (Current consumption): 7.5 mA Max。(fo = 25mhz, VCC = 3.3 V) 12.4 mA Max(fo = 125 MHz, VCC = 3.3 V) -频率公差(f_tol): SG-8200CG:±50 × 10-6(-40℃至+125℃)SG-8201CG:±15 × 10-6(-40℃至+105℃),±25 × 10-6(-40℃至+125℃)-相位抖动(tPJ): 1.1 ps(fo = 125 MHz,偏移频率:12 kHz至20 MHz)
了解更多请关注:Megaclk.com
#include <iostream> #include <bitset> using namespace std; void test_bitset(int i) { bitset<sizeof(char) * 8> bitset_byte(i);//定义并初始化 cout << "bitset of " << i << " is " << bitset_byte << endl;//直接可以被输出 if (bitset_byte.to_ulong() == i)//转换成整型 { //转换成 std::string cout << "bitset of " << i << " is " << bitset_byte.to_string() << endl; } cout << endl; } int main(void) { test_bitset(0); test_bitset(1); test_bitset(2); test_bitset(3); test_bitset(4); test_bitset(5); test_bitset(6); test_bitset(7); test_bitset(8); test_bitset(9); test_bitset(10); return 0; } 输出 bitset of 0 is 00000000 bitset of 0 is 00000000 bitset of 1 is 00000001 bitset of 1 is 00000001 bitset of 2 is 00000010 bitset of 2 is 00000010 bitset of 3 is 00000011 bitset of 3 is 00000011 bitset of 4 is 00000100 bitset of 4 is 00000100 bitset of 5 is 00000101 bitset of 5 is 00000101 bitset of 6 is 00000110 bitset of 6 is 00000110 bitset of 7 is 00000111 bitset of 7 is 00000111 bitset of 8 is 00001000 bitset of 8 is 00001000 bitset of 9 is 00001001 bitset of 9 is 00001001 bitset of 10 is 00001010 bitset of 10 is 00001010
500主要指的是服务器内部错误,即服务器遇到意外情况,无法完成请求导致返回出错。查看日志发现显示是访问权限问题(13: Permission denied),定位config配置问题。
解决方法如下:
1、查看nginx启动用户和使用用户是否一致
ps aux | grep nginx
如图:
一个是www,一个是root用户
2、打开nginx配置文件
打开 nginx.conf 文件
查找nginx.conf的位置
ps -aux | grep nginx
3、把 nginx 改为 root
4、重启nginx服务
service nginx restart
再使用查看命令
ps aux | grep nginx
如图:
访问接口,正常请求
介绍10个最新 Android Studio/IntelliJ IDEA 插件,助您提高工作效率!
微信搜索关注《Java学研大本营》
安卓开发插件是能够扩展集成开发环境(IDE)功能并提供额外功能的软件组件。这些插件可自动化任务、提高代码质量、优化性能和提高生产力。有许多可用于安卓开发的插件,包括支持特定框架或技术的插件,如Jetpack Compose。
以下是要介绍的插件:
1 计算器 计算器插件是可以安装在 IntelliJ / Android Studio 平台的 IDE 中的软件组件,用于提供高级数学表达式求值功能。它支持使用 mXparser 的所有有效表达式,这是一个针对 Java 和 .NET 平台高度优化的数学表达式解析库。通过这个插件,开发人员可以在 IDE 中轻松地进行复杂的数学计算,无需外部工具或库。这个插件对于从事大量数学计算的项目(如科学应用程序或金融分析工具)的开发人员非常有用。
安装链接:https://plugins.jetbrains.com/plugin/21246-calculator
2 Google 翻译 Google 翻译插件方便于开发人员将 strings.xml 或 arrays.xml 文件中的文本翻译成所需的语言。开发人员只需右键单击 XML 文件并选择 GoogleTranslate 选项,就可以选择要将文本翻译成的语言,然后点击 OK。使用这个插件,开发人员可以自动化翻译过程,省去手动翻译或切换到外部翻译工具的时间和精力。该插件还有助于确保应用程序本地化,以适应不同语言和地区的用户,这对于应用程序在全球市场的成功至关重要。
安装链接:https://plugins.jetbrains.com/plugin/21190-googletranslate
3 JetClient JetClient 是一款 REST(HTTP)客户端和 API 测试工具,具有比其他类似工具(如 Postman)更多的优势。它允许开发人员直接从源代码中导入 API,从请求导航到代码,反之亦然,并使用 Git 将请求集合与本地文件系统同步。此外,JetClient 还提供了高级环境和变量管理,以及用于预请求和测试脚本的强大脚本功能。虽然大多数功能都是免费的,但付费版本提供了额外的功能,如从源代码导入 API 集合和导航到源代码。JetClient 支持从各种框架(包括 cURL、Postman、Spring、JAX-RS、Retrofit 和 OpenAPI(Swagger))导入,更多的框架即将推出。JetClient 可以成为从事 RESTful API 开发的开发人员的有价值的工具,让他们可以简化其 API 测试和开发过程。
安装链接:https://plugins.jetbrains.com/plugin/21173-jetclient--the-ultimate-rest-client
4 Lorem Ipsum 生成器 Lorem Ipsum 插件是个简单的工具,可以让开发人员快速地在代码中生成占位文本。此插件易于使用,通过选择单词或段落,并可通过生成上下文菜单访问。此外,它适用于所有语言,是所有背景开发人员的多功能工具。Lorem Ipsum 插件可以通过自动化生成占位文本的过程节省开发人员的时间和精力,这在用户界面设计和开发项目中经常使用到。
题目 砍竹子 - 蓝桥云课 (lanqiao.cn)
思路和解题方法 #include <iostream> 是包含输入输出流的头文件。#include <cmath> 是包含数学函数的头文件。 接下来是程序的主要部分:
定义了一个类型别名 LL,表示 long long 类型。声明了数组 a 和 p,用于存储数据。在 main 函数中,首先读取输入的整数 n。使用循环读取 n 个数并存储到数组 a 中。同时,通过计算每个数的平方根(使用了 sqrtl 函数)并统计平方根的次数,将结果存储到数组 p 中,并找出最大的次数 max1。初始化变量 ans 为0,并在数组 p 的最后添加一个元素0。使用两个嵌套的循环,从最大次数 max1 开始递减,依次遍历数组 p 和数组 a。 如果当前元素 p[j] 不等于当前次数 i,则跳过本次循环。如果数组 a 中相邻的两个数相等,则不进行任何操作。否则,将 ans 加1,将 p[j] 减1,将数组 a 中的元素按照一定的计算方式更新为其平方根。打印输出最终的结果 ans。 复杂度 时间复杂度: O(n^2)
外层循环对 n 个元素进行遍历,时间复杂度为 O(n)。内层嵌套循环的时间复杂度需要根据具体情况来分析,因为它的时间复杂度依赖于 max1 的值和数组中元素的分布情况。 时间复杂度介于 O(n) 和 O(n^2) 之间,具体取决于 max1 的值和数组中元素的分布情况。
Python的正则表达式使用 定义使用场景查替换分割 常用的正则表达符号查原字符英文状态的句号点 .反斜杠 \英文的[]英文的()英文的?加号 +星号 *英文状态的大括号 {} 案例 定义 正则表达式是指专门用于描述或刻画字符串内在规律的表达式。
使用场景 无法通过切片,将字符串的子串返回。
借助于replace方法,无法完成非固定值或非固定位置值的替换。
借助于split方法,无法按照多种值实现字符串的分割。
查 findall(pattern, string, flags=0) pattern:指定需要匹配的正则表达式。
string:指定待处理的字符串。
flags:指定匹配模式,常用的值可以是re.I、re.M、re.S和re.X。re.I的模式是让正则表达式对大小写不敏感;re.M的模式是让正则表达式可以多行匹配;re.S的模式指明正则符号,即可以匹配任意字符,包括换行符\n;re.X模式允许正则表达式可以写得更加详细,如多行表示、忽略空白字符、加入注释等。
替换 sub(pattern, repl, string, count=0, flags=0) pattern:同findall函数中的pattern。
repl:指定替换成的新值。
string:同findall函数中的string。
count:用于指定最多替换的次数,默认为全部替换。
flags:同findall函数中的flags。
分割 split(pattern, string, maxsplit=0, flags=0) pattern:同findall函数中的pattern。
maxsplit:用于指定最大分割次数,默认为全部分割。
string:同findall函数中的string。
flags:同findall函数中的flags。
常用的正则表达符号 使用这些函数,需要导入re功能包
查原字符 指代直接存在于字符串内部的子串。
# 导入第三方包 import re # 提取出字符串中的Python子串 s1 = '看了博主的Python的文章,感觉Python很简单,学会了!' out1 = re.findall('Python', s1) print(out1) 输出:
[‘Python’, ‘Python’]
英文状态的句号点 . 英文的:‘.’ 指代任意字符(如数字、字母、标点符号、汉字等),但除了换行符\n。
# 导入第三方包 import re # 提取出动力的值 s2 = '此次宝马主要搭载了1.
按时间顺序爬取及批量爬取多页内容 按时间顺序爬取百度新闻一次性爬取多页内容爬取一家公司的多页信息爬取多家公司的多页信息 补充知识点:访问超时设置——timeout参数的使用 按时间顺序爬取百度新闻 按时间排列顺序:rtt=4
按热点排列:rtt=1
具体的网页改变都会使得对应的网页链接进行变化,所有我们只需要修改url即可了。
import requests import re headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'} def baidu(company): url = 'https://www.baidu.com/s?tn=news&rtt=4&bsst=1&cl=2&wd=' + company # 把rtt参数换成4即是按时间排序,默认为1按焦点排序 res = requests.get(url, headers=headers).text # print(res) p_href = '<h3 class="news-title_1YtI1"><a href="(.*?)"' href = re.findall(p_href, res, re.S) p_title = '<h3 class="news-title_1YtI1">.*?>(.*?)</a>' title = re.findall(p_title, res, re.S) p_date = '<span class="c-color-gray2 c-font-normal">(.*?)</span>' date = re.findall(p_date, res) p_source = '<span class="
串口模块CP2102usb TTL485 232 组成结构 使用方法 一般设置为usb-232-TTL
USART HMI软件 将制作好的屏幕显示编译成功后,选择对应串口,进行下载
下载波特率:115200
TJC3224T024_011 2.4寸显示屏 接口参数 端口解释 VCC:+5V
TXD:发送数据
RXD:接受数据
GND:接地
接线(特别注重) 烧入显示屏 效果
说在前面 不知道大家平时工作的时候会不会需要经常新建git分支来开发新需求呢?在我这边工作的时候,需求都是以issue的形式来进行开发,每个issue新建一个关联的分支来进行开发,这样可以通过issue看到一个需求完整的开发记录,便于后续需求回顾和需求回退。而我平时本地分支都不怎么清理,这就导致了我这两年来本地分支的数量达到了惊人的361个,所以便开始写了这个可以批量删除分支的命令行工具。
功能设计 我们希望可以通过命令行命令的方式来进行交互,快速获取本地分支列表及各分支的最后提交时间和合并状态,在控制台选择我们想要删除的分支。
功能实现 1、命令行交互获取相关参数 这里我们使用@jyeontu/j-inquirer模块来完成命令行交互功能,@jyeontu/j-inquirer模块除了支持inquirer模块的所有交互类型,还扩展了文件选择器、文件夹选择器及多级选择器交互类型,具体介绍可以查看文档:https://www.npmjs.com/package/@jyeontu/j-inquirer
(1)获取操作分支类型 我们的分支分为本地分支和远程分支,这里我们可以选择我们需要操作的分支类型,选择列表为:"本地分支"、"远程分支"、"本地+远程"。
(2)获取远程仓库名(remote) 我们可以输入自己git的远程仓库名,默认为origin。
(3)获取生产分支名 我们需要判断各分支是否已经合并到生产分支,所以需要输入自己项目的生产分支名,默认为develop。
相关代码 const branchListOptions = [ { type: "list", message: "请选择要操作的分支来源:", name: "branchType", choices: ["本地分支", "远程分支", "本地+远程"], }, { type: "input", message: "请输入远程仓库名(默认为origin):", name: "gitRemote", default: "origin", }, { type: "input", message: "请输入生产分支名(默认为develop):", name: "devBranch", default: "develop", }, ]; const res = await doInquirer(branchListOptions); 2、命令行输出进度条 在分支过多的时候,获取分支信息的时间也会较长,所以我们需要在控制台中打印相关进度,避免用户以为控制台卡死了,如下图:
3、git操作 (1)获取git本地分支列表 想要获取当前仓库的所有的本地分支,我们可以使用git branch命令来获取:
function getLocalBranchList() { const command = "git branch"
finebi 新手入门案例 连锁超市销售数据分析
步骤:
准备公共数据新建分析主题处理数据在数据中分析在图形中分析数据大屏 准备公共数据 点击公共数据 点击新建文件夹 修改文件夹名称 上传数据 鼠标悬停在文件夹上,右侧出现 +
鼠标悬停在文件夹上,右侧出现 +,点击 + 选择 Excel数据集
保存数据 保存数据前可以调整数据集,例如:数据类型、列位置
更新数据
新建分析主题 点击我的分析 点击新建分析主题 选择数据 处理数据 调整数据列 两种方式:
鼠标选中数据标题,拖拽即可
点击字段设置
在数据中分析 组件 图形和表格的载体,在组件内可以制作图形和表格并对对其进行编辑
点底部组件 维度与指标 维度 维度:分析数据的角度,例如:时间维度、空间维度、类别维度
指标 指标:维度上量化的值
商品销售额top10 需求分析:
维度:商品名称
指标:销售额
图表类型 使用分组表
定义维度 定义维度上的指标 销售额排序 销售额降序 鼠标悬停在指标中的销售额上出现下拉列表 在指标销售额下拉列表中选中过滤 添加条件下拉列表中选择且条件 在第一个条件下拉列表中选择最大的N个 调整参数如下图 效果图 修改组件名称 鼠标悬停在组件名称,长右侧出现三个点 点击重命名 或者直接双击组件名称,组件变为编辑状态 编辑完成后回车确认或者鼠标点击其它空白区域即可 商品毛利额 原始数据并没有毛利额,毛利额需要我们自己计算产生
毛利额 = 销售额 - 成本额
点击数据 在数据窗口点击新增公式列 计算公式列 毛利额 = 销售额 - 成本额
本文旨在讲解进程替换的知识!希望读完本文,能使读者对进程替换有更深一步的认识!!好的,废话不多说,干货来了!
进程替换的引进! 为什么要引进进程替换呢?我们创建子进程总不能做和父进程做一样的事情把!子进程也应该能做自己想做的事情吧!就拿我们日常生活中的例子来言:一个父亲经营一家公司,其儿子也不一定非得子承父业来选择和其父亲做一样的事情把。所以这就把进程替换这个概念引了进来!
进程替换的概念! 何谓进程替换呢?进程替换就是子进程不再运行父进程的代码和数据了,而是另起炉灶,选择新的代码和数据来执行!
既然进程替换的概念已经简单的介绍了,那么我们就来见一见进程替换把!
进程替换的实例 多进程的进程替换! 下面通过一个简单的多进程的代码来看一看什么是进程替换!
通过上图我们可以看出结果!子进程开始跑之后,调用了一个execl函数!然后父进程一直在跑!等待子进程的退出!最后通过监视进程窗口看见,子进程跑完了,但是子进程跑的代码是我们日常命令行中的ls命令?这难道进行进程替换么?
也有眼尖的小伙伴发现了,直至子进程退出之后,也没有执行其execl之后的代码!这是为什么?而且进程替换之后也没有创建新的进程!从这点我们可以看出,进程的替换并不会引起新的进程的产生!
那么为什么excel之后的代码就不再执行了呢?这就要从进程替换的原理来讲解了!
所谓的进程替换,本质上只是将子进程的代码和数据块进行了修改,其他的结构 并没有做出修改!那么是如何修改的呢?是从磁盘中获取新的代码和数据块,然后在内存中重新找空间,用于这些新的代码和数据块,然后修改子进程从父进程那边继承过来的页表的信息,简单的进程替换就做完了!
那么知道了原理,那该如何解释是如何进行进程替换的呢?
通过上面的调用execl函数可以看出,首先要找到被替换的可执行程序,然后进行选择如何执行这个程序即可!
要想彻底搞懂进程的替换原理,那么我们就不得不介绍系统提供的进程替换函数了!
进程替换函数讲解 通过上图我们可以看出进程替换有很多,他们都是在第三手册(也就是系统调用),下面我们就来详细介绍其中的一些函数!已经他们的使用方法!
execl 函数原型:
其中exec是这些函数的开头,l可以理解成list的意思,即用list传递参数!
可以看出,有两个参数!根据我们刚才多进程的进程替换的实例中,我们可以看出,其中第一个path就是替换后的程序的路径与文件名! 其中第二个参数就是我们日常在bash命令行中怎么写,就在函数传参怎么写就行!后面的三个点代码此函数是一个可变参数列表!表示参数不固定!但是需要注意的是:最后必须以NULL结尾,表示传参完毕!
execlp 函数原型:
其中exelc中的p代表的是PATH,即系统默认的PATH环境变量,所以第一个参数为file,表明只需要写你要替换的程序的名字即可!其中第二个参数上面execl中相同!
下面来看一下此函数的使用方式!
其中第一个参数,只需要将替换后程序的名字写上去就行,无需再进行声明路径即可!
execv 函数原型:
其中execv中的v代表的是一个数组,用于存放命令的选项!
下面来简单来看一下此函数的使用方式!
其中只需要创建一个函数指针数组即可,将程序的选项写入到argv数组即可!其中警告原因是因为前面没有用const修饰,因为它们指向的都是字符串常量!切记:此数组中的结尾也必须以NULL结尾,表示传递参数结束!
execvp 函数原型:
其中p代表的仍然是默认的环境变量,与execv的差距只是第一个参数传参不必再进行传路径了,只需要传被替换的程序名字即可!
使用就不再累赘了!
execvpe 函数原型:
其中e表示的环境变量!
表示该函数继承其父进程的环境变量,其中第三个参数指的是环境变量参数,可以传递系统自带的environ,或者自己自定义的环境变量的字符串指针数组!
具体使用如下:
只要将其中的参数进行正确的传参即可!其中第一个参数,也可以直接将arg[0]传入,第二个传的就命令行参数,第三个就环境变量参数,可以自己定义,也可以传系统自带的environ!
至此,将部分的exec簇家族的函数讲解一番,其他的函数只需要对照其上述的函数使用方式即可!
扩充:
但是当我们进行查找2号手册的时候,我们还会发现还有一个exel簇函数,它为什么在2号手册,和这些簇函数不同呢?
下面我们看一下2号手册的exec函数!
他为什么处于二号手册呢,这里简单介绍一番,其中位于三号手册的系统调用本质上都是调用的此函数!都是对本函数的封装!这是为什么呢?因为每次进程替换的时候,格式不确定,所以不能仅仅通过此函数来调用,因此就封装了这个函数,产生了位于三号手册的那些exec簇函数!
通过上述的进程替换我们可以看出,进程替换替换的都是bash命令行已经存在的命令,那么是否能够替换成我们自己写的程序呢?答案是肯定的!下面我就来写一个代码替换为我们自己写的C++进程!
Makefile
mytest.cc
运行之后,就可以看到将我们的代码替换成c++运行的代码了!
进程替换中环境变量的变化! 1.在进行进程替换的时候,子进程对应的环境变量,可以直接从父进程那边继承过来! 可以使用export新增导入环境变量观察即可!
2.环境变量被子进程继承下来是一种默认的行为,不受程序替换的影响!(因为程序替换只是简单的替换代码和数据段,然后修改页表中的部分内容,对虚拟地址空间也是直接拷贝过来!)
3.子进程获取环境变量的三种方式
一、直接原封不动的由父进程那边继承过来
二、传递自己定义的环境变量参数!
三、新增传递,即原封不动从父进程继承过来之后,再自己进行putenv()操作即可!
至此,关于进行替换的知识介绍完毕,希望能对读者有一定的收获!
文章目录 一、前言二、介绍各个消息中间件RabbitMQActiveMQRocketMQKafka 三、各个消息中间件对比四、总结 一、前言 上文简单讲述了何为消息队列和消息队列的特点(优点),本文为大家介绍一下各个消息中间件的特点和差距,主要对比的消息中间件有RabbitMQ、ActiveMQ、RocketMQ、Kafka。
二、介绍各个消息中间件 RabbitMQ RabbitMQ是一款使用Erlang语言开发的,实现AMQP(高级消息队列协议)的开源消息中间件。
组成:
Broker:消息队列服务进程。此进程包括两个部分:Exchange和Queue。Exchange:消息队列交换机。按一定的规则将消息路由转发到某个队列。Queue:消息队列,存储消息的队列。Producer:消息生产者。生产方客户端将消息同交换机路由发送到队列中。Consumer:消息消费者。消费队列中存储的消息。 特点:
可靠性。支持持久化,传输确认,发布确认等保证了MQ的可靠性。灵活的分发消息策略。这应该是RabbitMQ的一大特点。在消息进入MQ前由Exchange(交换机)进行路由消息。分发消息策略有:简单模式、工作队列模式、发布订阅模式、路由模式、通配符模式。支持集群。多台RabbitMQ服务器可以组成一个集群,形成一个逻辑Broker。多种协议。RabbitMQ支持多种消息队列协议,比如 STOMP、MQTT 等等。支持多种语言客户端。RabbitMQ几乎支持所有常用编程语言,包括 Java、.NET、Ruby 等等。可视化管理界面。RabbitMQ提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker。插件机制。RabbitMQ提供了许多插件,可以通过插件进行扩展,也可以编写自己的插件。 工作流程:
消息生产者连接到RabbitMQ Broker,创建connection,开启channel。生产者声明交换机类型、名称、是否持久化等。生产者发送消息,并指定消息是否持久化等属性和routing key。exchange收到消息之后,根据routing key路由到跟当前交换机绑定的相匹配的队列里面。消费者监听接收到消息之后开始业务处理。 ActiveMQ Apache ActiveMQ是最流行的开源,多协议,基于Java的消息代理。它支持行业标准协议,因此用户可以跨各种语言和平台获得客户端选择的好处。从用 JavaScript、C、C++、Python、.Net 等编写的客户端进行连接。使用无处不在的 AMQP协议集成您的多平台应用程序。在 Web 应用程序之间使用 STOMP通过 websockets 交换消息。使用MQTT管理您的物联网设备。支持您现有的 JMS基础架构及其他设备。ActiveMQ 提供了支持任何消息传递用例的强大功能和灵活性。
使用: 需要Java JDK
特点:
服从 JMS 规范:JMS 规范提供了良好的标准和保证,包括:同步或异步的消息分发,一次和仅一次的消息分发,消息接收和订阅等等。遵从 JMS 规范的好处在于,不论使用什么 JMS 实现提供者,这些基础特性都是可用的;
连接性:ActiveMQ 提供了广泛的连接选项,支持的协议有:HTTP/S,IP 多播,SSL,STOMP,TCP,UDP,XMPP等等。对众多协议的支持让 ActiveMQ 拥有了很好的灵活性。
支持的协议种类多:OpenWire、STOMP、REST、XMPP、AMQP ;
持久化插件和安全插件:ActiveMQ 提供了多种持久化选择。而且,ActiveMQ 的安全性也可以完全依据用户需求进行自定义鉴权和授权;
支持的客户端语言种类多:除了 Java 之外,还有:C/C++,.NET,Perl,PHP,Python,Ruby;
代理集群:多个 ActiveMQ 代理可以组成一个集群来提供服务;
异常简单的管理:ActiveMQ 是以开发者思维被设计的。所以,它并不需要专门的管理员,因为它提供了简单又使用的管理特性。有很多中方法可以监控 ActiveMQ 不同层面的数据,包括使用在 JConsole 或者 ActiveMQ 的Web Console 中使用 JMX,通过处理 JMX 的告警消息,通过使用命令行脚本,甚至可以通过监控各种类型的日志。
用链表存储的线性表如果只有每个节点只有一个指针域,则称为单链表。
单链表由结点组成,而结点通常由数据域和指针域构成,存储定义代码如下:
struct LNode { int data; LNode* next; LNode(int value) { data=value; next=nullptr; } }; 单链表的节点的指针域其实可以简单理解为存储着寻找下一个相同类型节点的指针,形成一个简单的套娃。
单链表的一个重要概念就是头结点和头指针。头结点是链表中的第一个节点,建立一个头结点和头指针,方便对链表进行修改,删除,查询等操作。
class LinkList { private: LNode* head; LNode* rail; public: LinkList() { head=new LNode(0); rail=head; } } 创建一个链表最基本的方法有两种——头插法和尾插法。
头插法:头插法即每次插入节点都在头结点之后,通过头插法创造出来的链表与插入的顺序相反。如图:新建一个结点S,如果想把结点S插入头结点之后,那需要我们先找到头结点后一个的结点,S结点与其进行连接,之后在将头结点与S结点相连接。其中,重要的是不能更换操作顺序,如果先把头结点和S结点相连接,则会导致断链,无法找到原来与头结点相连接的结点。
代码如下:
void headend(int value) //头插法 { LNode* s=new LNode(value); s->next=head->next; head->next=s; } 尾插法:即将结点每次插入在链表的尾部,利用尾插法构建的链表是顺序。
尾插法需要我们设置一个表尾指针P,初值指向头结点,每次新建一个结点S,结点插在表尾指针P之后,之后S成为新的表尾。代码如下:
void append(int value) //尾插法 { LNode* s=new LNode(value); rail->next=s; rail=s; } 通过头插法和尾插法构造出链表之后,可以通过指针进行对链表的基础操作,例如查询链表中是否有指定的元素ELEM,其思想主要是通过设置工作指针进行对链表的遍历,代码如下——
bool getElem(int i) { LNode* d=head->next; while(d!=nullptr){ if(d->data==i) return true; else d=d->next; } return false; } 删除和更改链表指定位序的元素——其思想主要是通过指针对指定位序进行定位,之后通过设置新的指针对其数据域进行操作。
条件:已经在本地git和github上建了仓库,并在本地已经add了github的仓库
下拉出问题:
$ git pull --rebase origin main
fatal: unable to access 'http://github.com/5cu77756465/nand2tetris.git/': OpenSSL SSL_read: Connection was reset, errno 10054
上传出问题
$ git push -u origin main
error: src refspec main does not match any
方法:多pull几次,会成功,我就是这样子,可能是网络或者其他问题。不过只有pull了才能push(这里如果有意见可以指正)。
add:还有一个补充,要push之前你先add文件再commit,这个文件不能是空的文件夹。
(欢迎指正或补充,这只是我的经验之谈)
T terminate called after throwing an instance of 'std::bad_alloc’问题
W 出问题的程序段
using PointT=pcl::PointXYZ; using PclT=pcl::PointCloud<PointT>; PclT::Ptr res; pcl::ConditionalRemoval<PointT> condrem; condrem.setCondition(range_and); condrem.setInputCloud(pcIn); res.reset(new PclT()); condrem.filter(*res); 编译时警告
/usr/bin/ld: warning: libpcl_filters.so.1.8, needed by ../../../perceptor/lib/libperceptor.so, may conflict with libpcl_filters.so.1.10 注意版本冲突,没有在link_directories连接指定的库
link_directories(LIB_DIR/third_libs/pcl/lib) 改过来就好了
分别用两种方法动态添加option:
方法一:JS方法添加
1、创建select标签
var select = documnet.createElement(‘select’);
2、给select添加id
select.setAttribute(‘id’,‘selectid’);
3、给select添加onchange事件
select.setAttribute(‘onchange’,‘change();’);
4、将select添加到body里面
document.body.appendChild(select);
5、给select里面动态添加option
select.options.add(new Option(‘label’,‘value’));
方法二:Jquery方法添加
页面已经有select标签,可以直接往里面添加option。
$(‘#selectid’).append(‘text’);
两种方法获取选中的option的值和value
方法一:js方法获取
1、获取select对象
var select = document.getElementById(‘selectid’);
2、获取选中的option的索引值
var index = select.selectedIndex;
3、获取选中option的value
var selectedValue = select.options[index].value;
4、获取选中option的text
vat selectedText = select.options[index].text;
方法二:jQuery方式获取
1、获取选中的option
var select = $(‘#selectid option:selected’);
2、获取选中option的value
var selectValue = select.val();
3、获取选中option的text
var selectedText = select.text();
一个小例子:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script src="./js/jquery.min.js"></script> <script> window.
css 字体倾斜 //左右倾斜 transform: skew(40deg, 0deg); //上下倾斜 transform: skew(0deg, 16deg);
如何识别和获取reCAPTCHA的数据 步骤1:确定需要提交的数据 首先,需要确定您要解决的reCaptcha是否需要提交数据。如果在需要时未提交此数据,将导致无效的令牌或令牌无效的可能性很高。要确定是否需要s数据,请使用Capsolver的验证码检测功能。可以在此处进一步了解此工具:
了解Capsolver的验证码检测器
当需要数据块时,**Capsolver**的扩展将显示一个如下所示的显示面板:
步骤2:找到获取此值的位置 此阶段涵盖获取s数据值的过程。首先打开"检查"工具(F12),切换到网络选项卡,并激活reCaptcha。会出现一个请求URL,类似于:
/fc/gt2/public_key/613F48sD7-3DCD-468D-8557-CFF418CF794D
请注意,‘sitekey’ 部分 (613F48sD7-3DCD-468D-8557-CFF418CF794D) 会有所不同。检查POST请求的有效负载,将找到一个"s data"参数,您可以从中复制该值。
接下来,在"检查"工具中按下CTRL + S打开搜索面板。在此处输入s数据值,将显示生成此值的请求。
在某些情况下,如果该值为HTML编码、加密或位于其他位置,则此方法可能无效。建议检查每个请求的响应正文,以确定该值的来源位置。请注意,此值每次都会更改。因此,在每次提交验证码之前重新提取它非常重要,以确保验证码令牌保持有效。在指定所需格式的数据时,应按以下方式输入:
"enterprisePayload": { //Optional, required if the website uses recaptcha enterprise "s": "[VALUE]" }, 以上就是使用Capsolver的插件如何识别和获取reCAPTCHA的数据,获取reCAPTCHA参数教程,大家可以参考一下。
CapsolverCN官方代理交流扣 群:497493756
这里我是用我本地训练的基于yolov8环境的竹签计数模型,在打开摄像头窗口增加了实时计数显示的代码,可以直接运行,大家可以根据此代码进行修改,其底层原理时将检测出来的目标的个数显示了出来。
该项目链接:【目标检测】保姆级别教程从零开始实现基于Yolov8的一次性筷子实时计数,从数据集构建到模型训练与部署,手把手教学-CSDN博客
项目模型:【免费】基于yolov8的竹签计数的模型文件资源-CSDN文库
import cv2 from ultralytics import YOLO # 加载模型 model = YOLO(model=r"D:\yolov8\runs\detect\train\weights\best.pt") # 摄像头编号 camera_no = 1 # 打开摄像头 cap = cv2.VideoCapture(camera_no) while cap.isOpened(): # 获取图像 res, frame = cap.read() # 如果读取成功 if res: # 正向推理 results = model(frame) # 绘制结果 annotated_frame = results[0].plot() # 获取检测到的物体的数量 num_objects = len(results[0].boxes) if results and results[0].boxes else 0 print(f"竹签个数: {num_objects}") # 在图像左上角显示物体数量 cv2.putText(annotated_frame, f"Number: {num_objects}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示图像 cv2.
服务器500错误是一个常见的错误代码,也就是服务器遇到了一个预料之外的错误,无法正常处理请求。这个错误通常是由于服务器配置错误、程序代码问题或者服务器资源不足等原因引起的。对于网站管理员和用户来说,服务器500错误则意味着网站无法打开,因为它不仅会影响网站的可用性和用户体验,还可能会对网站的形象和信誉造成负面影响。
解决服务器500错误需要采取一系列的措施,可以通过以下几个方面解决:
1. 检查服务器日志
服务器日志是解决服务器500错误的关键。通过查看服务器日志,可以了解错误的详细信息,包括错误发生的时间、错误的类型以及错误发生的上下文等。这些信息可以帮助管理员更好地理解错误的来源和原因,从而采取相应的措施。
2. 重新启动服务器
有时候,服务器500错误可能是由于服务器资源不足或程序代码问题引起的。在这种情况下,重新启动服务器可能会解决问题。重新启动服务器可以清除掉内存中的垃圾数据和释放占用的资源,从而让服务器重新恢复正常运行。
3. 检查程序代码
如果服务器500错误是由于程序代码问题引起的,那么需要检查程序代码并进行修复。在检查程序代码时,在IIS中打开网站功能视图,找到并打开错误页,在错误页界面右侧点击"编辑功能设置...",在错误响应中钩选"详细错误",确定即可。在IIS中打开网站功能视图,找到并打开错误页,在错误页界面右侧点击"编辑功能设置...",在错误响应中钩选"详细错误",确定即可。
在浏览器设置中选择“Internet选项”,取消勾选“显示友好HTTP错误信息”,点击“确定”。
通过以上两种方法刷新页面后可看到详细的错误信息,通过错误信息去检查相应代码问题。
需要注意以下几点:
* 检查程序代码是否有语法错误或逻辑错误;
* 检查程序代码是否能够正确处理异常情况;
* 检查程序代码是否有安全漏洞或恶意代码注入的风险;
* 检查程序代码是否能够与服务器环境兼容。
4. 优化服务器配置
如果服务器500错误是由于服务器配置错误引起的,那么需要优化服务器配置。在优化服务器配置时,可以查看iis-网站-身份验证-匿名身份验证(编辑)-选择应用池标识,同时需要注意以下几点:
* 检查服务器硬件配置是否满足应用程序的要求;
* 检查服务器操作系统和应用程序的版本是否更新到最新;
* 检查服务器的安全设置是否正确配置;
* 检查服务器的内存、CPU和磁盘等资源是否合理分配。
5. 寻求专业帮助
如果以上措施都无法解决服务器500错误,那么需要寻求专业帮助。可以联系网站管理员或技术支持团队,向他们报告错误的情况和细节,并寻求他们的帮助来解决错误。在寻求帮助时,需要注意提供尽可能多的错误信息和细节,以便管理员或技术支持团队更好地理解和解决问题。
安全狗团队专业防护服务器安全,可以帮助您解决服务器安全中存在的各种隐患和错误,如果您有这方面的需求欢迎致电安全狗,或者到安全狗官网联系在线客服。
总之,解决服务器500错误需要仔细检查各个方面并采取相应的措施。通过检查服务器日志、重新启动服务器、检查程序代码、优化服务器配置以及寻求专业帮助等方法,可以有效地解决服务器500错误,并确保网站的可用性和用户体验。
一,图像检测 用已经训练好的模型进行图像推理检测,运行时注意修改图像和模型路径。
# 引入opencv import cv2 # 引入YOLO模型 from ultralytics import YOLO # 打开图像 img_path = "./img.jpg" # 这里修改你图像保存路径 # 打开图像 img = cv2.imread(filename=img_path) # 加载模型 model = YOLO(model="yolov8n.pt") # 这里修改你图像保存路径 # 正向推理 res = model(img) # 绘制推理结果 annotated_img = res[0].plot() # 显示图像 cv2.imshow(winname="YOLOV8", mat=annotated_img) # 等待时间 cv2.waitKey(delay=10000) # 绘制推理结果 cv2.imwrite(filename="jieguo.jpeg", img=annotated_img) 二, 视频检测 用已经训练好的模型进行视频推理检测,运行时注意修改图像和模型路径。
import cv2 from ultralytics import YOLO # 加载模型 model = YOLO(model="yolov8x.pt") # 视频文件 video_path = "
1. 取得某一个属性的值
let obj = {'name':'lxc','age':26}
方法一:点号操作符 obj.name
方法二:方括号操作符:obj[name]
方法三:解构赋值 let {name} = obj
...
2.取得对象的key和value值
let obj = {'name':'lxc','age':26}
取Object key值
方法一:Object.keys(obj) //['name','age'] 返回一个字符串数组
方法二:for in
for(let i in obj){
console.log(i); //name,age
}
...
Object value值
方法一:Object.value(obj) //['lxc',26] 返回一个字符串数组
方法二:for in
for(let i in obj){
console.log(obj[i]); //lxc,26
}
方法三:map
Object.keys(obj).map((key)=>{ console.log(obj[key])}) //lxc,26
3.对象合并(会将key值相同的进行覆盖去重操作)
方法一:Object.assign
const a = { a: 1, b: 4 }
const b = { b: 2, c: 3 }
目录
前言
1.分布式锁
1.基于单个节点
2.基于多个节点
3.Redisson分布式锁 4.watch(乐观锁) 2.原子操作
1.单命令操作
2.Lua 脚本(多命令操作)
3.事务
1.执行步骤
2.错误处理
3.崩溃处理
总结
前言 在多个客户端并发访问Redis的时候,虽然Redis是单线程执行指令,但是由于客户端指令达到Redis的时序无法保证,所以可能出现如下的情况,导致并发问题。
2个客户端都执行 get, set指令,期望将key的值设置为3,结果因为并发问题,导致结果为2 client1 get x => 1 client2 get x => 1 client1 set x => 2 client2 set x => 2 本文介绍 Redis 并发方面的解决方案。
Redis 的单个命令是原子的,但是一个业务操作可能包含多条命令,比如以下场景:客户端查询值,并递增,在高并发场景下就可能出现并发问题,导致数据不一致。
为了保证并发访问的正确性,Redis 提供了三种方法,原子操作、分布式锁、事务。
1.分布式锁 与分布式锁相对的是本地锁,假如只有一个服务实例,就可以直接在该单应用本地使用锁变量来控制多个客户端的访问。
如果使用的是多实例的分布式系统,就需要使用分布式锁,即将锁保存在一个第三方的共享存储系统中,可以被多个客户端共享访问和获取。通常将一个 Redis 实例作为分布式锁的存储系统。
实现分布式锁的关键在于:
保证每个加锁、释放锁操作都是原子的;保证共享存储系统的可靠性,即锁的可靠性; 分布式锁相较于 Lua 脚本,更简单易用,但是分布式锁的性能不如 Lua 脚本。 Lua脚本只能用于对Redis的操作,但是分布式锁不限,可以用于任何场景,例如对mysql数据库的操作。 1.基于单个节点 Redis 提供了 SETNX 命令(在 SET 命令后加上 NX 选项也能达到同样的效果),保证了加锁操作的原子性。
后端采用springboot+webSocket+redis能扛着万人在线。
目录
什么是Redis
Redis特性
速度快
丰富的功能
客户端语言多
持久化
主从复制
Redis可以做什么
缓存
排行榜系统
计数器应用
消息队列系统
Redis安装
centos7安装
Redis重要文件
Redis的使用
Redis通用命令
set get
keys
exists
del
expire
什么是Redis Redis是⼀种基于键值对(key-value)的NoSQL数据库,与很多键值对数据库不同的是,Redis
中的值可以是由string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、Bitmaps(位图)、HyperLogLog、GEO(地理信息定位)等多种数据结构和算法组成,因此Redis可以满⾜很多的应⽤场景,⽽且因为Redis会将所有数据都存放再内存中,所以它的读写性能⾮常惊⼈。不仅如此,Redis还可以将内存的数据利⽤快照和⽇志的形式保存到硬盘上,这样在发⽣类似断电或者机器故障的时候,内存中的数据不会“丢失”。除了上述功能以外,Redis还提供了键过期、发布订阅、事务、流⽔线、Lua脚本等附加功能。总之,如果在合适的场景使⽤Redis,它就会像⼀把瑞⼠军⼑⼀样所向披靡。
Redis特性 速度快 正常情况下,Redis的速度是非常快的,官方给出的速度是10万/秒,当前也是取决于机器的性能,这里不考虑机器的性能,我们只是分析一下是什么造就了Redis拥有如此快的速度.
高效的数据结构 redis使用动态字符串,哈希表,List集合,双向链表,压缩列表,和跳跃表等数据机构来实现数据存储,这样能将数据高效的存储和读取出来.
基于内存的操作, redis所有的操作都是基于内存的,并且大多数操作都是简单的存储和获取,而存取的大部分操作都消耗在I\O上,而I\O操作最快的就是内存了.
多路I\O复用模型, 多路指的是多个网络连接,复用指的是复用一个线程,这使得redis在单线程的基础上处理多个并发请求.多路复用内部采用epoll代理来实现,epoll会同时监测多个流的I\O事件,当没有事件时,就会阻塞.
单线程执行,单线程执行可以避免因为多个线程过度的抢占和调度而产生的时间.
丰富的功能 除了5中基本的数据结构,Redis还提供了很多的额外的功能.
1. 提供了键过期功能,用于实现缓存
2. 提供了发布订阅功能,用于使用消息系统
3. 提供了lua脚本功能,可以使用lua创造出新的Redis命令
4. 提供了事务管理功能,能在一定程度上保证事务特性
客户端语言多 Redis提供了简单的TCP协议,很多编程语言都可以轻松的接入Redis,,所以支持Redis客户端的语言也非常多,包括C、C++、Java、PHP、Python、NodeJS等.
持久化 因为Redis的数据是存储在内存中的,所以要是发生断电等极端情况,数据就会丢失,但是对于Redis来说,数据是不会丢失的,因为Redis提供了两种持久化功能:RDB,AOF,即可以使用这两种策略将内存的数据存储到硬盘中.这样就保持了数据了的持久化.
主从复制 Redis提供了复制功能,实现了多个数据的Redis副本.复制功能是分布式Redis的基础
Redis可以做什么 缓存 缓存机制几乎在所有的大型网站都有运用,合理的使用缓存不仅可以提高数据访问的速度,而且能够有效的降低后端数据源的压力.
一个合理的缓存设置能够为一个网站提供稳定的的使用体验.
排行榜系统 对于某些网站需要提供一个排行榜的功能,Redis提供了列表和有序集合的结构,能够轻松的实现排行榜功能.
计数器应用 计数器在⽹站中的作⽤⾄关重要,例如视频⽹站有播放数、电商⽹站有浏览数,为了保证数据的
实时性,每⼀次播放和浏览都要做加1的操作,如果并发量很⼤对于传统关系型数据的性能是⼀种挑
战。Redis天然⽀持计数功能⽽且计数的性能也⾮常好,可以说是计数器系统的重要选择。
消息队列系统 消息队列系统可以说是⼀个⼤型⽹站的必备基础组件,因为其具有业务解耦、⾮实时业务削峰等
特性。Redis提供了发布订阅功能和阻塞队列的功能,虽然和专业的消息队列⽐还不够⾜够强⼤,但是对于⼀般的消息队列功能基本可以满⾜
Redis安装 关于Redis的安装,我们将linux系统上进行安装.
centos7安装 使用yum安装
起因是下载了一个数据集:KDD
解压了如图所示的文件:
发现爆炸了,满屏幕的文件。。。
想删除包含特定文件名称的文件,当文件名过长时也能实现删除的作用
# 方式一:删除包含某个字符的文件,不支持特殊名称文件 rm *00. # 方式二:删除除某些文件夹外的文件,不支持中文文件夹 rm !(filename1 | filename2) # 方式三:一个一个删除,不支持长文件名称且费力 rm abcd.................... # 方式四:找到名称中包含某个字符的文件,并删除(解决方案) find . -name "*00*" | xargs rm -rf
电脑出问题了,导致git仓库像是被损坏了一样,执行git status就会报错unable to read ree,无法正常提交代码至仓库,原因是本地代码仓库.git文件损坏了,无法找到正确的提交历史和路径。
找到了一个解决办法:
线上代码仓库所有代码合入,至最新状态(这一步很关键,不然复制了也对不上);然后将线上代码库客隆下来,执行以下操作: # 进入本地拉取的线上项目副本文件夹 cd copy/path/to/project # 将副本文件夹中的.git文件复制到本地损坏了.git文件的项目文件夹中 cp -r .git path/to/local_modified_project/ 利用线上仓库.git文件修复本地损坏的文件,再进行git status或者commit就正常了。
还有一个问题就是如果不小心在子文件夹下进行了git init命令,导致文件夹下文件的状态不对,但此时根目录下所有的文件状态已经通过上述步骤修复,原因是在子文件夹下执行init会新建一个子目录仓库,从而导致状态不一致,此时可以通过以下步骤修复:
# 进入子项目目录 cd sub_project # 删除不小心新建的.git文件 rm .git 然后在配置中重新配置git至根目录路径即可:
Memory day1 [root@zxd ~]# timedatectl Local time: 六 2023-08-26 14:11:06 CST#当地时间 Universal time: 六 2023-08-26 06:11:06 UTC#世界时间 RTC time: 六 2023-08-26 06:11:05#实时时钟时间 Time zone: Asia/Shanghai (CST, +0800)#时区,CST即东八区时间 NTP enabled: no#NTP未开启,NTP是国家时间规划 NTP synchronized: no#NTP同步未开启 RTC in local TZ: no#实是时钟不是当地时钟 DST active: n/a#夏令时有效 不适用 #主要是看时区用的命令
[root@zxd ~]# date 2023年 08月 26日 星期六 14:39:02 CST #查看系统时间 [root@zxd ~]# date -R Sat, 26 Aug 2023 14:39:50 +0800 #查看时区(数字形式) [root@zxd ~]# date -s '2077-12-12 11:11:11' 2077年 12月 12日 星期日 11:11:11 CST #'年-月-日 中间至少有一个空格 时:分:秒' #修改系统时间的命令 [root@zxd ~]# date "
crontab每分钟定时执行: */1 * * * * service mysqld restart //每隔1分钟执行一次 */10 * * * * service mysqld restart //每隔10分钟执行一次 crontab每小时定时执行: 0 */1 * * * service mysqld restart //每1小时执行一次 0 */2 * * * service mysqld restart //每2小时执行一次 crontab每天定时执行: 0 10 * * * service mysqld restart //每天10点执行 30 19 * * * service mysqld restart //每天19点30分执行 0 05 0 * * /bin/bash /home/update_course_day.sh //每晚十二点五分执行.sh脚本 crontab每周定时执行: 0 10 * * 1 service mysqld restart //每周一10点执行 30 17 * * 5 service mysqld restart //每周五17点30分执行 crontab每年定时执行: 0 10 1 10 * service mysqld restart //每年的10月1日10点执行 0 20 8 8 * service mysqld restart //每年的8月8日20点执行 时间段执行: 1-59 0-2 * * * /bin/bash // 凌晨0点到2点执行 1-59 2-4 * * * /bin/bash // 凌晨两点到四点执行 作者:一位先生_ 链接:https://www.
刚开始尝试了很多种方式,例如,deep..啦,还有官方自带的dropdownStyle属性,最离谱还看见一个文章 再index.html文件中设置样式,但是这样可以设置成功,但我相信,一个稍微资深一点的vue开发者都不想再index.html中设置样式,包括后期管理起来不方便什么的...。
ok话不多说了,直接上教程。
其实教程也很简单,只需要设置:
<a-select :getPopupContainer="(triggerNode)=> triggerNode.parentNode || document.body;" > </a-select> 这个方法其实就是用来将下拉框展开后的 框。渲染绑定到 这个属性设置的节点上。这样根据class就能定位到了。
这个属性还有一点好处,就是如果下拉框有的时候点击或者滚动页面的时候,下拉框也会跟着滚动。设置这样属性便可以固定了。
*小知识:如果下拉框不展示 placeholder 设置的值。是因为 placeholder 只有在 value = undefined 才会显示,对于其它的 null、0、'' 等等对于 JS 语言都是有意义的值。
一、基础语法 1.1 函数装饰器 Python装饰器(Decorator)是一种特殊的函数,其可以装饰其他的函数或类。所谓装饰,其实就是将其他的函数或类作为参数传入,在原有基础上添加一些新逻辑或者属性后,将这个新的函数或类返回的过程。
我们首先来看函数装饰器,这里给出一个例子。
# 一个简易的示例装饰器 def myDecorator(func): def wrapper(*args, **kwargs): print("这里是添加的装饰器逻辑") return func(*args, **kwargs) return wrapper # 被装饰函数 def example(): print("这里是被装饰的函数") # 装饰过程 example = mydecorator(example) # 调用被装饰后的函数 example() # 调用结果 # >> 这里是添加的装饰器逻辑 # >> 这里是被装饰的函数 上面这段代码中,我们首先定义了一个装饰器函数,该函数以其他函数为形参,并返回一个新的函数对象。(请注意,在Python中函数本身就是一等对象,即可以被当作形参传递、当作返回值返回,也可以被存储在数据结构中)
在装饰过程中,example这一变量被装饰器返回的新函数对象所替代。 因此在之后的调用中,结果里显示了装饰器导入的打印逻辑。这就是函数装饰器的原理。
1.2 @Wrapper语法糖 上面的代码和大家之前了解的装饰器画风可能不太一致。
事实上,装饰器本身只是函数的一种用法,而Python为了方便大家应用这种技巧,提供了一种语法糖,来快速应用装饰器函数。
# 使用@wrapper装饰器语法来快速应用装饰器函数 @myDecorator def example(): print("这里是被装饰的函数") 这段代码与1.1中的装饰过程是等价的,程序员使用@mydecorator语法时,等价于使用example = mydecorator(example)对example函数进行装饰。也就是说,被装饰的函数对象会作为参数传入装饰器函数,因此,请确保你的装饰器函数拥有合适数量的形参以接收被装饰函数对象。
从语法上讲,@后面可以连接任何赋值表达式,最简单的情况就是我们直接给出装饰器函数名。如果是其他类型的表达式,也只需确保表达式的返回值是一个可调用的函数对象即可(这一点为后面的含参装饰器提供了支持)。
1.3 类装饰器 之前讲到,类与函数都可以通过装饰器进行装饰。装饰函数实际就是返回一个新函数对象,对于类而言道理相同,就是返回一个新的类对象而已。请注意这里的类对象不是指类的实例,而是指类类型对象(对,这个类对象的类型就是type)。可以简单的理解为重新给出了被装饰类的定义。对一个类的装饰包括但不限于添加新的方法与属性,当然也可以覆盖或重写原类型的方法与属性。下面给一个简单的示例:
# 定义类装饰器 def myDecorator(cls): class Wrapper: def __init__(self, *args, **kwargs): self.
fast.js 文件中,大约135行左右:
var area = Fast.config.openArea != undefined ? Fast.config.openArea : [$(window).width() > 800 ? ‘80%’ : ‘95%’, $(window).height() > 600 ? ‘80%’ : ‘95%’];
microsoft edge 浏览器驱动:
https://developer.microsoft.com/en-us/microsoft-edge/tools/we
bdriver/
谷歌浏览器驱动:
CNPM Binaries Mirrorhttps://registry.npmmirror.com/binary.html?path=chromedriver/119版本驱动:Chrome for Testing availability
火狐浏览器驱动:
https://github.com/mozilla/geckodriver/releases
poi生成的折线图和柱形图,用wps打开正常,用office打开显示损坏,报错“已删除的部件: 部件 /xl/drawings/drawing1.xml。 (绘图形状)”
测试版本:poi 4.1.2 、Office 2021。
1、修复思路 既然wps能正常打开,那就使用wps打开另存为新的excel,发现新的excel在office中能正常打开,对比新旧两个excel的xml,找出不同的地方的xml,最后根据这个xml使用代码来修复。
2、生成一个简单的折线图 复杂的折线图、柱状图、饼图可以参考我的另一篇文章:https://blog.csdn.net/u014644574/article/details/105695787
package com.study.test; import org.apache.poi.xddf.usermodel.chart.*; import org.apache.poi.xssf.usermodel.*; import java.io.FileOutputStream; import java.io.IOException; /** * POI EXCEL 图表-折线图 */ public class PoiLineChart { public static void main(String[] args) { FileOutputStream fos = null; try { XSSFWorkbook wb = new XSSFWorkbook(); XSSFSheet sheet = wb.createSheet("Sheet1"); // 创建一个画布 XSSFDrawing drawing = sheet.createDrawingPatriarch(); // 画布起始位置(左上角):x=0,y=3。画布占列数:7-0=7列。画布占行数:26-3=23行 XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 3, 7, 26); // 创建一个chart对象 XSSFChart chart = drawing.
你好,我是清风徐来
上周五,写了篇《ChatGPT4 最新开通方法!不需要验证手机,不需要等待》,很多小伙伴按照这篇指引,一步步开通了 GPT PLUS ,用上了 GPT4!
这两天不少小伙伴来问,如何申请 API KEY
今天就来分享一下:如何申请官方 GPT4 API 接口、申请通过后如何在国内直联使用,最后讲讲官方计费方式
一、相关概念 1、什么是 API ?
答:你可以把 chatgpt 当做一个巨大的能量池
你有两种方式可以使用它
第一,通过官方的网站 chat.openai.com
第二,通过 API 接口,API = 程序调用接口
通过 API 这个“水管”,你可以将 chatgpt 这个能量池用接入到你自己或者第三方程序中,
比如人见人爱的“清风 AIchat”,以及今天要介绍的 NEXT WEB,就是调用了 API 接口。
2、什么是 API KEY?
每个 API 接口有一把钥匙。有了这把钥匙,才能打开接口,就是 API KEY
3、开通了 GPT4,就默认有 GPT4 的 API KEY 么?
答:非也。需要单独申请。以前需要等待,现在预付 5 美元即可申请开通。
另外,11 月之前 GPT3.5 账号申请成功后,官方默认赠送了 5 美元 API 额度;现在新申请 GPT3.5 账号 取消了赠送,但是你可以按照本篇文章介绍的方法,申请 3.
查找错误日志文件存储路径 用到的软件:everything
官网
voidtools
下载路径
https://www.voidtools.com/Everything-1.4.1.1024.x64-Setup.exe
直接点击下载即可
运行效果如下 我们知道mysql有个配置文件是my.ini,里面配置了相关信息
我们需要先查这个文件在哪里
下图中我们看到路径在C:\ProgramData\MySQL\MySQL Server 5.7\my.ini,也直接双击打开该文件
可以看到日志相关配置
错误日志文件的路径如下
# Error Logging. log-error="WIN-UCL3QDDK1UB.err" 我们再在everything中搜索WIN-UCL3QDDK1UB.err
直接打开即可
查看日志
一、下载源码 SDL官网
二、编译 2.1、脚本目录 2.2、安装msys2官网 2.3、进入脚本目录 cd /d/android/chrome/sdl2-2.28.5/sdl2-2.28.5/build-scripts 2.4、执行脚本 ./androidbuild.sh 2.5、脚本传入参数,生成android项目 ./androidbuild.sh com.aniljing.sdl ../test/testdraw2.c 2.6、使用android studio打开项目
1. 什么是高可用? 高可用(High Availability, HA)是指在信息技术中确保系统、服务或应用程序在绝大多数时间内都是可操作和可访问的能力。这通常涉及以下几个关键方面:
最小化停机时间:
高可用系统的目标是减少因硬件故障、系统升级、维护或其他原因导致的停机时间。这通常通过冗余设计实现,例如使用多个服务器或组件,如果一个出现故障,另一个可以立即接管。 故障转移和冗余:
故障转移是指当一个系统组件失败时,自动切换到备用系统或组件以继续运行。冗余指的是多余的备份组件,如额外的服务器或网络连接,以保证主组件故障时的连续性。 快速恢复:
当系统发生故障时,能够迅速恢复正常运行是高可用性的重要组成部分。这可能涉及快速诊断和解决问题的能力,或者能够快速重启或切换到备用系统。 可扩展性和性能:
高可用系统通常需要具备良好的可扩展性,以应对负载增加。系统性能也是重要考虑因素,以确保在高负载下仍能提供满意的服务。 数据完整性和备份:
高可用系统需要确保数据不会因系统故障而丢失或损坏。定期备份和数据冗余是确保数据安全的关键措施。 高可用性不仅仅是技术上的实现,它还涉及到组织的政策、流程和人员培训。确保系统高可用性是许多组织特别是提供关键服务或拥有大量用户的组织的重要目标。
Redis通过多种机制来保证其高可用性(HA),确保数据库服务在面对各种挑战时能够保持运行。以下是Redis实现高可用性的主要方法:
主从复制(Master-Slave Replication):
Redis允许设置一个主节点和多个从节点。所有的写操作都在主节点上执行,然后数据被复制到从节点。如果主节点出现故障,从节点可以提供读服务,保持数据的可访问性。 哨兵模式(Sentinel):
哨兵是一种监控系统,它监控Redis主从节点的健康状况。如果主节点失败,哨兵会自动将从节点提升为新的主节点,实现故障转移。它还可以通知应用程序关于主节点的变更,帮助应用程序快速适应新的主节点。 集群模式(Cluster):
Redis集群通过自动分片和数据复制在多个节点之间分布数据。每个主节点都有至少一个复制节点,以确保数据的持续可用性。在主节点失效时,其复制节点会自动被提升为新的主节点。 持久化:
Redis提供了RDB(快照)和AOF(只追加文件)两种数据持久化方式。这些持久化方法可以保证在系统故障后数据不会丢失,并能够恢复到故障发生前的状态。 定期检查和维护:
定期对Redis系统进行检查和维护,可以预防潜在的问题,保持系统的稳定运行。 备份和恢复策略:
定期备份Redis数据,以便在发生灾难性事件时可以迅速恢复。 通过这些机制,Redis能够在各种情况下保持高可用性,即使在面对节点故障、网络问题或其他意外情况时也能保证服务的连续性和数据的安全性。
2. 主从复制 Redis,作为一个广泛使用的内存数据库,以其快速性和灵活性而著称。在众多特性中,Redis的主从复制功能是实现高可用性和数据备份的重要机制。
什么是主从复制? 主从复制是一种常见的数据复制和备份方法。在Redis的上下文中,它涉及将数据从一个主节点自动复制到一个或多个从节点。主节点负责处理写操作,而从节点则用于读取操作和作为数据的备份。这种机制不仅提高了数据的可用性,还增加了系统的读取能力。
工作原理 初始同步 启动复制过程:复制过程始于从节点向主节点发送一个同步命令。数据快照:主节点接收到同步命令后,会创建一个当前数据的快照。传输快照:主节点将这个快照文件传输到从节点。加载快照:从节点接收并加载这个快照,从而复制主节点的数据状态。 增量同步 一旦初始同步完成,接下来就是增量同步过程。在此阶段,主节点会持续将所有新的写命令发送给从节点。从节点实时接收并应用这些命令,确保自己的数据状态与主节点保持一致。
主从复制的优势 数据冗余:主从复制提供了数据备份,增加了数据的安全性。读写分离:通过从节点处理读取请求,可以减轻主节点的负载,提高系统的整体性能。故障恢复:如果主节点出现故障,可以从从节点中选举一个新的主节点,以此实现快速的故障恢复。 使用场景 数据备份:在数据备份方面,主从复制确保了即使主节点失效,数据仍可从从节点恢复。负载均衡:在读密集型应用中,可以通过增加从节点数量来分担读取负载。灾难恢复:在多地部署时,即使某一地区的服务器出现故障,其他地区的服务器仍能保持服务的连续性。 Redis的主从复制是一种强大而灵活的功能,它为Redis用户提供了一种简单高效的方式来实现数据备份和高可用性。无论是在提升系统性能、保障数据安全,还是在实现灾难恢复方面,主从复制都扮演着不可或缺的角色。了解并合理利用这一功能,将有助于更好地发挥Redis的潜力,实现更加稳定和高效的数据管理。
3. 哨兵模式 在当今数据驱动的时代,数据库的可靠性和高可用性至关重要。Redis,作为一个广受欢迎的开源内存键值数据库,不仅以其高性能著称,还提供了一种被称为“哨兵模式”的机制,以保证数据库的高可用性。本文将详细介绍Redis哨兵模式的工作原理、特点及其应用。
什么是哨兵模式? 哨兵模式是Redis用于实现高可用性的一种机制。在这个模式下,有一个或多个独立的哨兵进程监控Redis的主从服务器。哨兵的主要任务是监控Redis服务器,自动执行故障转移,并提供服务发现功能。
工作原理 哨兵模式的工作可分为几个核心步骤:
监控:哨兵会不断检查主节点和从节点的健康状况。通知:当某个节点出现问题时,哨兵会通知系统管理员或其他应用。自动故障转移:如果主节点失效,哨兵会自动从从节点中选举一个新的主节点,并重新配置其他从节点以复制新的主节点。配置提供者:哨兵还充当配置提供者的角色,客户端可以询问哨兵以获取当前的主节点地址。 故障转移流程 当主节点失效时,哨兵将自动执行以下步骤来恢复系统:
确认主节点故障:当多个哨兵(通常是大多数)同意主节点失效时,才会开始故障转移。选举新的主节点:哨兵会从现有的从节点中选出一个作为新的主节点。配置更新:新的主节点配置将被更新,并通知所有的从节点,让它们开始复制新的主节点。 哨兵模式的优势 高可用性:自动故障转移机制保证了即使主节点宕机,数据库仍能快速恢复。无需人工干预:系统能够在不需要人工干预的情况下自动恢复,减少了维护成本。服务发现:客户端可以自动发现当前的主节点,简化了配置和管理。 使用场景 哨兵模式适用于以下场景:
关键业务应用:对于需要24/7运行的关键业务应用,哨兵模式提供了不间断服务的保障。动态环境:在云环境或虚拟化环境中,哨兵模式可以适应动态变化的网络条件。自动化运维:适合希望减少人工运维工作的环境。 Redis哨兵模式是一种强大且灵活的高可用性解决方案,它通过自动监控和故障转移,确保了Redis服务的持续可用性。无论是对于大型企业级应用还是对于要求高度可靠性的系统,哨兵模式都是一种值得考虑的选择。通过充分理解和正确配置哨兵模式,可以大大提高Redis数据库的稳定性和可靠性。
4. 集群模式 Redis的集群模式,它为处理大规模数据提供了一个可靠的解决方案。本文将详细且通俗地介绍Redis集群模式,帮助你理解它是如何工作的以及为什么它如此重要。
什么是Redis集群模式? Redis集群是Redis提供的一种分布式数据库解决方案。它允许你将数据自动分割(分片)到多个Redis节点上。每个节点保存数据的一个子集,这种方式提高了数据处理的性能和可扩展性。即使在某些节点出现故障的情况下,集群也能保持数据的可用性和持续服务。
集群模式的工作原理 数据分片 Redis集群通过分片来管理数据。整个数据空间被划分为16384个槽(slot),每个Redis节点负责维护一部分槽。当添加、获取或删除数据时,Redis会根据键计算出它应该去的槽,然后将操作路由到负责该槽的节点。
在 macOS 中,要删除本地 Maven 仓库中所有的 .lastUpdated 文件,您可以使用 find 命令结合 rm 命令来执行这个操作。这可以在终端(Terminal)中完成。
打开您的终端应用程序,然后使用以下命令:
find ~/.m2/repository -name "*.lastUpdated" -type f -delete 这里的 find 命令解释如下:
~/.m2/repository 是本地 Maven 仓库的默认位置。如果您的 Maven 仓库在不同的位置,需要相应地修改这个路径。-name "*.lastUpdated" 指定了要搜索的文件名模式。-type f 表示您只想查找文件类型。-delete 是告诉 find 命令删除找到的所有匹配文件。 在执行这个命令前,请确保您明白这将删除所有匹配的文件,这个操作是不可逆的。如果您希望在删除之前先检查一下哪些文件会被删除,您可以先运行不带 -delete 的命令:
find ~/.m2/repository -name "*.lastUpdated" -type f 这会列出所有将被删除的 .lastUpdated 文件。如果您确认这些是您想要删除的文件,再执行带有 -delete 选项的命令。
确保在执行这些命令时,您有足够的权限来删除这些文件。如果需要,您可能要在命令前添加 sudo 来获取管理员权限。
基础模型 transformers- attention is all you need 细节笔记
论文笔记 几个重点 1. 架构图
2. attention 原理
attention机制中的query,key,value的概念解释
3. 为什么self-attention?为什么multi-head attention?
rnn 是ht的结果是根据ht-1的结果计算得到,无法并行的计算,这也是推出transfomers最根本的理由。
根据这个图,Self Attention就是让Attention中的q、k、v相等,所以self attention其实得到的是输入序列中每个部分与整个序列其他部分的关系,注意q、k、v来自于同一个向量但是经过了不同的投影矩阵,因此q、k、v是不一样的。
我们直接来看transformer中的Self Attention结构图,可以看到transformer是使用的Dot-Product Attention的变体(多除了个根号d,d是输入序列的通道数,目的是为了防止Q与K转置的内积过大或过小导致梯度较小),但因为d是设置好的超参数(常数),因此两者其实没有太大差别。
的结果就是Q和K的相似度,经过softmax使其变为0到1的数值后作为V的权重。
可以看到上述过程其实就是一系列的矩阵运算,并不包含任何参数,只有上图右侧中的Linear层是可学习的,而Linear层的作用是将Q、K、V投影到高维语义空间(也就是multi-head attention的作用)。所以上述的Self Attention操作实际上是在计算高维语义空间的Q和K的相似度作为V的权重进行了特征融合以获取全局信息。那么说明我们其实是通过喂数据给模型,指导其学会投影出这么一个语义空间——在此空间中我们期望相似的Q与K具有很高的相似度。
举个句子生成的例子来说,我们以Hello作为模型的输入,World作为下一个词的ground truth,只有当Hello和Word在投影出来的空间中具有较高的相似度,我们的attention机制才会给World较高的权重从而让模型输出World,那么通过自注意力的计算和梯度下降,我们就能让Linear学会让两个词投影到相近的位置
4. 为什么position encoding?
对于序列的seq / rnn 是有时序信息的。而对于Transformer来说,由于句子中的词语都是同时进入网络进行处理,顺序信息在输入网络时就已丢失。一句话概括,Positional Encoding就是句子中词语相对位置的编码,让Transformer保留词语的位置信息。
CV领域 vision transformer的笔记 DETR: End-to-End Object Detection with Transformers clip 论文 笔记
论文笔记
多模态鸿沟
数据集:四亿的图文对,进行对比学习。
对比学习,就是需要正样本和负样本的定义。在这里的正样本就是已经配对好的,反之就是负样本。所以有N个正样本,有N2 -N个负样本
clip 做目标检测 Open-Vocabulary Object Detection
clip 做图像分割 CLIPSeg
Image Caption 领域 李飞飞经典 Deep Visual-Semantic Alignments for Generating Image Descriptions
要修改Git仓库的远程地址,你可以使用以下命令:
查看当前的远程地址:
git remote -v 修改远程地址:
git remote set-url origin <新的远程地址> 在这个命令中,你需要将 <新的远程地址> 替换为你想要设置的新的远程地址。然后,你就可以使用 git remote -v 命令再次验证远程地址是否已经修改成功。
VMware虚拟机Linux系统磁盘扩容 很多小伙伴使用VMware创建虚拟机,时常会选择默认磁盘大小20G,
用着用着才发现20G不够用,服务启动不了。
让我们今天一起来解决一下,VMware虚拟机Linux系统磁盘扩容。
查看磁盘空间 df -h 重点关注 框选的逻辑卷名称
每个系统的名字不一定相同
但都是 /dev/mapper 开头 后面的是逻辑卷名称
步骤: 虚拟机添加新磁盘为新磁盘创建分区格式化新创建的分区为刚刚格式化的分区创建物理卷将刚刚创建的物理卷添加的需要扩容的逻辑卷下增加文件系统大小验证扩容前后对比 虚拟机添加新磁盘 编辑虚拟机设置
添加选择磁盘后,点击下一步
勾选推荐的磁盘类型,点击下一步
勾选创建新的磁盘,点击下一步
设置最大磁盘大小,勾选将磁盘存储为单个文件,点击下一步
完成向导
确认虚拟机设置
添加新磁盘后的虚拟机
查看磁盘信息 fdisk -l 红框中文新增磁盘
创建分区 使用 fdisk /dev/sdb 创建分区,根据向导完成以下操作
先输入n 新建分区
后输入 p 主分区
选择分区起始位置 回车即可使用默认值
选择分区结束位置 回车即可使用默认值
然后输入 wq 保存并退出
这样就创建了一个大小为200G的分区
fdisk /dev/sdb 格式化新创建的分区 mkfs 即 make filesystem 创建文件系统
常见的 Linux 文件系统为 xfs 和 ext4
本案例 使用的是 xfs 文件系统
mkfs.xfs -f /dev/sdb1 ext4和XFS是Linux操作系统中常见的两种文件系统。它们都是现代的高性能文件系统,各自具有优缺点。以下是它们之间的比较:
09-鸿蒙4.0学习之ForEach循环渲染 代码
/** * 循环渲染 * todo:重点注意键值生成器返回的数据,保证唯一性,否则某些相同的数据会渲染不出来 * */ @Entry @Component struct Loop { @State message: string = '循环渲染' @State product:string[] = ['第一项','第二项','第三项','第四项','第四项'] @State arrList:object[]=[ { id:'001', title:'hellworld1', content:'内容1' }, { id:'002', title:'hellworld2', content:'内容2' }, { id:'003', title:'hellworld3', content:'内容3' } ] build() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) Divider() ForEach(this.arrList,(item)=>{ Text(item.content).fontSize(30) },(item)=>{ return item.id // 返回值为 字符串 表示唯一性 类似于ID }) } .width('100%') } .height('100%') } }
08-鸿蒙4.0学习之If、else条件判断语句 代码
@Entry @Component struct Branch { @State isShow: boolean = false build() { Row() { Column() { Button('切换') .fontSize(50) .fontWeight(FontWeight.Bold) .onClick(() => { this.isShow = !this.isShow }) Text(this.isShow ? '显示' : '不显示') if(this.isShow){ Branch_Comp({content:'我是显示情况下的子组件'}) }else{ Branch_Comp({content:'我是不显示情况下的子组件'}) } } .width('100%') } .height('100%') } } @Component struct Branch_Comp { content: string = '自有' build() { Column() { Text(this.content) } } } // 作业:写个逢七过的游戏
打开configs文件下,选择一个要用的网络来训练的.py文件,右键,复制绝对地址
2、修改地址表达:粘贴到某处,都改为\\以防出错。
4、回到train.py,右键运行。没有下载会自动下载。
(或者直接在下方Terminal用指令python tools/train.py xxx.py 代替3-4步骤)
5、运行后会报错,也就会生成文件。位置在tools/work_dirs下
6、复制粘贴到configs下,后续就用这个文件的基础上修改,这样操作更全面。
7、对该文件进行修改。:
改两个class=1,改max epoch = 5,改train val test路径 ,改学习率 降低weight_decay = 0.0002,改load_from = xxx.pth',改samples_per_gpu=2,workers_per_gpu=1或0,(网络比较复杂就改小,网络简单小的话就改大一些,比如在SSD中,samples_per_gpu=16也可以)
8、coco.py修改(和数据集json文件中对应相等才行,否则报错。记得下面颜色也改为对应数量)
9、修改完毕,再次修改参数为当前位置的文件(复制当前位置绝对路径到Train.py的配置中)。最终在train.py右键运行。(或者使用指令python tools/train.py xxx.py)
出现问题:
1、 runner.logger.info('loss become infinite or NaN!')
AssertionError: None
降低学习率 weight_decay = 0.0002
2、UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xd3 in position 0: invalid continuation byte
env_info['MSVC'] = cc.decode(encoding).partition('\n')[0].strip()
改为:env_info['MSVC'] = cc.decode(encoding,"ignore").partition('\n')[0].strip()
decode()增加一个ignore就可以了
目录 一次MySQL数据库迁移实战背景1.备份 demo 数据库2.恢复demo数据库 一次MySQL数据库迁移实战 背景 由于之前安装的mysql因为磁盘、cpu、内存等,不满足现有使用需求,需要升级主机配置,只能重新在更高的主机上安装新的mysql。同时,将现有数据库迁移至新的mysql主机。
于是有了下面迁移实战,为避免不必要的麻烦,以下教程信息已经脱敏。
1.备份 demo 数据库 1)登录mysql安装服务器
登录机器:ssh tkops@192.168.10.173
2)执行mysql备份命令
# 创建备份文件目录 mkdir /data01/update0719/ cd /usr/local/mysql/bin ./mysqldump -u demo -h localhost -p demopwd > /data01/update0719/20230719_demo_all.sql cp /usr/local/mysql/bin/20230719_demo_all.sql /data01/update0719/ 3)发送备份文件到mysql 188 目标机器:
scp /data01/update0719/20230719_demo_all.sql tkops@192.168.10.188:/data01/demo_update/ 2.恢复demo数据库 恢复mysql demo数据库至新的mysql主机。
1)登录mysql 升级版主机
ssh tkops@192.168.10.188 2)使用root登录mysql
cd /data01/local/mysql5.7 # 使用root用户登录mysql管理控制台 ./bin/mysql -u root 3)执行初始化数据库-授权及创建库
use mysql; #创建demo用户,密码请根据实际情况设置,并记录下密码 grant ALL PRIVILEGES ON demo.* TO demo@"%" IDENTIFIED BY "demopwd" WITH GRANT OPTION; flush privileges; #创建数据库 create database if not exists demo default character set utf8 collate utf8_general_ci; 4)恢复备份数据
详解利用指针求数组的最大值与最小值 通过指针来求解数组的最大值和最小值是一种常见的做法。指针在 C/C++ 中可以直接操作数组的元素,使得代码更加灵活。以下是一个简单的示例,演示如何使用指针找到数组的最大值和最小值: #include <iostream> void findMinMax(const int* arr, int size, int* min, int* max) { // 初始时将最小值和最大值设置为数组的第一个元素 *min = *max = arr[0]; // 使用指针遍历数组 for (int i = 1; i < size; ++i) { // 如果当前元素比最小值小,则更新最小值 if (arr[i] < *min) { *min = arr[i]; } // 如果当前元素比最大值大,则更新最大值 if (arr[i] > *max) { *max = arr[i]; } } } int main() { const int size = 5; int arr[size] = {10, 5, 8, 2, 15}; int minValue, maxValue; // 调用函数找到数组的最小值和最大值 findMinMax(arr, size, &minValue, &maxValue); std::cout << "
什么是Helper类? Helper类是一个包含一些常用方法或功能的类,用来辅助完成某个模块或任务的功能。它们通常不是直接提供业务功能的类,而是被其他类调用来完成一些特定的任务。Helper类的作用是提高代码的重用率、可维护性和可测试性,减少代码的冗余、依赖性和耦合度。在面向对象编程中,Helper类通常被归类为工具类或辅助类。
什么是Utility类? Utility类是一种实用工具类,它包含一组静态方法,目的是提供常用的实用方法,例如字符串处理、日期处理、文件操作等。通常,它不应该被实例化,因为不需要其状态,而是通过调用静态方法来使用其中的功能。Utility类通常作为工具库或框架的一部分提供给开发人员使用。
Helper类特点 辅助类:Helper类是用于完成一些辅助性任务的类,它们通常包含一些静态方法或常量,用于封装一些功能并提供简单易用的接口。
与主要业务逻辑无关:Helper类不包含主要的业务逻辑,它们仅用于提供辅助性功能,比如格式化日期、处理字符串等。
可重用性:Helper类通常是可重用的,它们可以被不同的模块或组件使用,并且不需要进行修改。
简化代码:使用Helper类可以简化代码,避免重复编写相同的功能代码,同时也提高了代码的可维护性和可读性。
Utility类特点 1. 静态方法:Utility类通常具有静态方法,因为它们不需要实例化,可以直接从该类中访问方法。
2. 无状态:Utility类不需要存储任何状态或数据,它们的方法只是执行一些操作并可能返回结果。
3. 不可变性:Utility类的方法通常不会改变传入的参数的状态,也不会改变类的状态或数据。
4. 实用功能:Utility类提供实用功能,通常涉及计算、转换或处理数据的方法。
5. 简单易用:Utility类的设计旨在简单易用,使开发人员可以轻松地使用它们的方法来解决各种问题。
6. 通用性:Utility类通常提供通用的方法,可用于不同的应用程序或场景。
Helper类代码示例: 在下面的示例中,Helper类通过注解@Service声明为Spring管理的Bean,并通过注解@Autowired注入了UserRepository,然后实现了一些通用的业务逻辑方法,例如创建用户和根据ID获取用户等。这些方法可以在应用程序中被其他组件调用,从而减少了代码的重复编写。通过注解@Transactional,Helper的createUser方法也被声明为一个事务。
@Service public class Helper { @Autowired private UserRepository userRepository; @Transactional public User createUser(String name, String email, String password) { User user = new User(); user.setName(name); user.setEmail(email); user.setPassword(password); return userRepository.save(user); } public User getUserById(Long id) { return userRepository.findOne(id); } //其他业务逻辑方法... } Utility类代码示例: Java中的utility类通常是包含静态方法的类,用于处理通用问题,例如日期处理、字符串处理、文件操作等。下面是一个示例utility类:
public class Utility { /** * 判断字符串是否为空或null * @param str 字符串 * @return true or false */ public static boolean isNullOrEmpty(String str) { return str == null || str.
公司新项目依赖较多,扩展版本参差不一,搭建环境复杂缓慢,所以搭建了一键部署的功能。
docker-compose build 构建docker
docker-compose up 更新docker
docker-compose up -d 后台运行docker
docker exec -it docker-php-1 /bin/bash 进入项目所在的容器内
docker logs docker-php-1 查看项目日志
docker-compose down 关闭所有服务
公司新项目依赖较多,扩展版本参差不一,搭建环境复杂缓慢,所以搭建了一键部署的功能。
准备工作,确保安装了docker并且已启动,否则会安装新docker
目录提权:cd /Users/macuser/.docker/buildx/current
添加本地dns : sudo vim /etc/hosts
git clone 项目到本地
切换到项目中的docker目录
cd /Users/macuser/wdsxiaozhu/spiderv2/docker
执行shell命令
sh install.sh
docker 目录独立出来,方便添加多个项目,
本地项目目录/Users/macuser/www
docker创建并启动
添加一个新项目 docker/nginx/vhost,复制现有的conf,改写成新项目的配置信息
添加hosts
sudo vim /etc/hosts
重启docker下的nginx
docker compose restart nginx
进入docker下的项目目录 docker exec -it docker-php-1 /bin/bash
cd ..
ls -l
cd xiaozhuquan-platfrom/
远程连接记录查看:
查看远程登录的IP地址和连接时间等。
一、从服务端查看登录的client记录
二、从本地的注册表查看登录过的server的记录
可清除日志。
要清除:
应用程序和服务日志 > Microsoft > Windows > TerminalServices- RemoteConnectionManager,其他的也要看下
如何查询windows远程桌面连接历史记录?
以下已经验证了:
Windows server 2019/Windows 11/win7
Windows server 2012
Windows server 2008
Windows 10
一、从服务端查看登录的client记录信息 S1、Win+R,winver
屏幕剪辑的捕获时间: 11/13/2023 9:19 AM
S2、Win+R,eventvwr.msc
导航到:应用程序和服务日志 > Microsoft > Windows > TerminalServices- RemoteConnectionManager,右键单击“Operational”并选择“筛选当前日志”。
S3、远程桌面服务的事件ID是1149,然后输入1149过滤日志。
S4、然后,您将获得一个事件列表,其中包含与该服务器的所有远程桌面连接的历史记录。
点击其中之一,即可看到远程桌面连接的详细信息,包括IP地址、计算机名、登录时间等。
屏幕剪辑的捕获时间: 11/13/2023 9:32 AM
这里是我通过防火墙端口映射远程的信息。
二、从本地的注册表查看登录过的server的记录 S1、win+R,regedit
导航到:HKEY_CURRENT_USER > SOFTWARE > Microsoft > Terminal Server Client > Default,然后您就可以看到已经建立的远程桌面连接。
这里可以看到从本地登录过的远程服务端的历史记录信息。
点击terminal server client子目录下的servers查看本机保存的登录过的远程服务端的一些信息,如远程账号等。
Winserver2019、win7的信息和win11的基本一致
Pytorch安装 PyTorch
pip安装 pip install torch==1.7.1+cu110 torchvision==0.8.2+cu110 torchaudio==0.7.2 -f https://download.pytorch.org/whl/torch_stable.html 使用使用pip安装pytorch不会安装cudatoolkit(不知道会不会产生问题)
conda安装 conda install pytorch==1.7.1 torchvision==0.8.2 torchaudio==0.7.2 cudatoolkit=11.0 -c pytorch 报错(待解决) 使用conda安装pytorch时在import torchvision时会报错:
ImportError: DLL load failed while importing _imaging: 找不到指定的模块 为jupyter添加kernel #安装ipykernel conda install ipykernel #添加kernel python -m ipykernel install --name conda_env_name python -m ipykernel install --user --name conda_env_name -- kernel_name #查看所有kernel jupyter kernelspec list #删除特定的kernel jupyter kernelspec uninstall your_kernel_name
前言 随着时代的发展,现如今我们生活上已经随处可见的各种电子产品了,诸如手机、平板、电脑、一些其它智能单品上都有用到显示屏,它作为人机交互的重要桥梁之一,我认为它是生活中必不可少的存在,如果少了它,那么这个世界也就缺失了独有的那份色彩。
那么此篇文章我们就好好讲讲TFT-LCD屏的“故事”,下文将以lcd屏信号类型和接口模式展开。
相关博文推荐 嵌入式LCD软件驱动流程与调试
1.LCD屏常用接口模式 1.1 RGB模式 RGB模式接口通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及三者组合来得到丰富多彩的颜色,它们三者之间的组合几乎包括了人类视觉感知的所有颜色,是最常用的颜色体系之一。
通常数据格式有rgb565、rgb666、rgb888等;拿rgb565举例,红色、绿色和蓝色的数据分别有5bit、6bit和5bit,那么它就可以有65536种组合色彩,在色彩要求不是特别高的应用场景中已经够用了。
RGB接口LCD 的显存是由系统内存充当的,因此其大小只受限于系统内存的大小,显示数据直接写到屏里,速度较快。
1.2 MCU模式 MCU-LCD 接口的标准术语是 Intel 提出的 8080 总线标准(标准名称为I80),主要又可以分为 8080 模式和 6800 模式,这两者之间主要是时序的区别。
MCU 接口的 LCD 的 Driver IC 都带 GRAM,Driver IC 接收 MCU 发过来的画点Command/Data,使之在屏上显示出来,这个过程是不需要点、行、 帧时钟的。因为MCU接口屏是经过IC GRAM的,它的内存空间没这么大,所以很难做到大屏(大多4寸以下)。相比RGB接口屏,MCU屏的显示速率慢,需要通过控制命令来刷新显示,通常用于静态界面的显示。
1.2.1 8080模式 由数据总线和控制总线两部分组成,控制引脚如下:
CS :片选信号,通常低电平有效;
RS :(置 1 为写数据,置 0 为写命令);
WR :写控制(为 0 使能) ;
RD :读控制(为 0 使能);
RESET: 复位信号;
DATA:数据位,支持8、9、16、18、24bit,通常默认8bit。
1.2.2 6800模式 该模式和8080模式很类似,总线控制读写信号组合在一个引脚上(/WR),另外增加了一个锁存信号(E)。
锁存信号(E)用于控制指令和数据的传输;MCU需要在E信号的上升沿将数据写入LCD屏的数据端口,当E信号为高电平时,LCD屏处于数据读取状态,可以接收来自MCU的数据,并在E信号的下降沿将数据锁存到LCD屏的内部寄存器中,这样可以避免数据的丢失或错位。
CS :片选信号,通常低电平有效;
RS :(置 1 为写数据,置 0 为写命令);
人如果要出人头地,一定要学会有效沟通.
沟通漏斗
沟通的角度,沟通的方向
沟通有三个方向,分别是向上沟通 没有胆,向下沟通 没有心和水平沟通 没有肺。
沟通的个人障碍,即地位的差异
信息过滤,信息也有过滤的现象,在公司内部,当上情不能下达,下情不能上达时,信息就在中间呗过滤掉了。
缺乏反馈的后遗症就是,讲话的人不继续解释了,而听话的人就照自己错误理解去做事。
简化语言
简洁的语言是智慧的灵魂,冗长的语言是肤浅的藻饰。说话漫无边际,啰哩啰嗦,会让听的人摸不着头脑,甚至感觉厌恶,失去倾听的兴趣。说话的人一定要简化语言,同时还要注意谈话技巧。
讲话要有重点。因为一个人在跟别人沟通的时候,不是自己想讲多长时间就可以讲多长时间的,你怎么知道客户要给你多长时间呢?
心理学研究证明,人的注意力只有10分钟。如果你在10分钟内没有抓住客户的注意力,他就没有兴趣了,即使你后来给她讲再多的东西,对他来讲,也已经是废话了。
主动倾听的作用,让对方感受自己受到了尊重。在我们跟别人沟通的时候,如果能主动倾听,让别人先讲话,对方就会感觉你跟尊重他,他自然乐意与你沟通,合作。
不要任意打断别人的谈话,因为这样只会招致别人的反感,认为你很不礼貌,而且还会打击对方谈话的积极性。
克服沟通阻碍有三种方法,利用反馈,简化语言和主动倾听。
在沟通时要充分利用反馈,做到事前问清楚,事后负责任。
要简化你的语言,突出谈话重点,还要善于运用比喻说明问题,这样会让你的沟通更顺畅。
沟通是一个有序的循环过程,你需要先用心地倾听,再搞清楚自己是否已经明白,然后向对方提出你的观点,最后确保对方了解你的观点。
Unity如何使用ILDasm工具查看IL代码 项目目录\Library\ScriptAssemblies
静态成员函数为什么不能调用非静态成员变量 然而从本质上来说类的静态成员函数的函数形参中没有默认的this指针,导致不能调用具体实例对象的成员
因为静态方法在类加载的时候就已经初始化,但非静态的资源要在类手动创建对象new出来以后才会存在
静态方法存在的时候无法保证它访问的非静态资源存在,就算能保证存在,你也无法知道获得的是哪个对象的非静态资源
in 修饰符(只读),指定参数由引用传递,可以由调用方法读取,但不可以写入。 引入 in 参数的原因
我们知道,结构体实例的内存在栈(stack)上进行分配,所占用的内存随声明它的类型或方法一起回收,所以通常在内存分配上它是比引用类型占有优势的。
但是对于有些很大(比如有很多字段或属性)的结构体,将其作为方法参数,在紧凑的循环或关键代码路径中调用方法时,复制这些结构的成本就会很高。当所调用的方法不修改该参数的状态,使用新的修饰符 in 声明参数以指定此参数可以按引用安全传递,可以避免(可能产生的)高昂的复制成本,从而提高代码运行的性能。
out 修饰符,指定参数由引用传递,必须由调用方法写入。 ref必须先赋值,因为ref在函数内可以不赋值
⼀、ref(引⽤型参数)和out(输出型参数)的区别
1、使⽤ref型参数时,传⼊的参数必须先被初始化,out型参数,必须在⽅法中对其完成初始化。
2、使⽤ref和out时,在⽅法的参数和执⾏⽅法时,都要加Ref或Out关键字,以满⾜匹配。
3、out适合⽤在需要retrun多个返回值的地⽅,⽽ref则⽤在需要被调⽤的⽅法修改调⽤者的引⽤的时候。
5、系统对ref的限制是更少⼀些的。
6、若要使⽤ ref 参数,必须将参数作为 ref 参数显式传递到⽅法,ref 参数的值被传递到 ref 参数。
7、当希望⽅法返回多个值时,声明 out ⽅法⾮常有⽤;使⽤ out 参数的⽅法仍然可以返回⼀个值。
8、ref 将值类型强制按引⽤类型进⾏传递
很多人可能会觉得这时候因为引用类型赋值时是传递的地址,那这时候第一个元素应该是3才对啊。我们来画图分析一下!
也就是,引用类型的数组new了一个新数组,就意味着在堆内存中重新开辟了内存空间,当前变量指向的地址也会随之改变。所以当改变了array后并没有影响到外部的arr数组。
【唐老狮】C#——ref和out - 知乎 (zhihu.com)
第一步:安装库(取消请求用)
npm install --save yet-another-abortcontroller-polyfill
第二步:写上传组件 & 使用 上传组件:组件中分片传,仅最简单实现(分片传),秒传&断续上传暂未实现。 /* * @Description: 上传&查看文件组件(手动上传,大文件分片上传,取消上传, 点击文件名可在线预览) */ import { ProFormUploadButton } from '@ant-design/pro-components'; import { App } from 'antd'; import type { UploadFile } from 'antd/es/upload/interface'; import type { UploadChangeParam, UploadProps } from 'antd/es/upload'; import { getToken } from '@/utils/getToken'; import PreviewImg from '@/components/PreviewImg'; import { useState, useRef, forwardRef, useImperativeHandle } from 'react'; import { ALLOWED_FILE_TYPE } from '@/utils/const'; import { isPicture } from '@/utils/index'; import { createMultipartUploadUsingPOST, completeMultipartUploadUsingPOST, } from '@/services/xx/FileInfoController'; import { partFileUploadUsingPOST, uploadFileUsingPOST, } from '@/services/file-related/FileInfoController'; import 'yet-another-abortcontroller-polyfill'; // const ACTION_URL = process.
1 代码 通过.bind
<el-row v-for="(item, index) in buildSiteWorkForm.work" :key="index"> <el-col :span="3"> <el-form-item class="wrap" label="设备清单" prop="officeEquipmentFile"> <el-upload class="upload-demo" action="" :auto-upload="false" ref="officeEquipmentFileRef" accept = ".pdf, .PDF" :on-change="officeEquipmentFileChangeHandle.bind(null, index)" :on-remove="officeEquipmentFileRemoveHandle.bind(null, index)"> <el-button size="mini" type="primary">上传</el-button> </el-upload> </el-form-item> </el-col> </el-row>
一、查询JDK 打开终端,执行查询命令,查看可用的jdk版本,下图红框中的就是具体版本
sdk list java 二、安装SDK 使用下面的命令安装指定版本jdk,版本号获取方法:步骤一👆🏻
sdk install java <version> 三、切换默认JDK sdk default java <version> 当前使用的jdk如图,可以看到现在默认使用的是jdk17,现在使用👆🏻的命令,切换默认jdk为8
执行命令:
sdk default java 8.0.352-zulu 再使用命令查看当前默认的jdk:
sdk list java 此时已经切换成功。
四、卸载JDK sdk uninstall java <version> sdk 其它命令可使用 sdk help 查看
标题:磁砖样式
小明家的一面装饰墙原来是 310 的小方格。
现在手头有一批刚好能盖住2个小方格的长方形瓷砖。
瓷砖只有两种颜色:黄色和橙色。
小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
小明有个小小的强迫症:忍受不了任何22的小格子是同一种颜色。
(瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)
显然,对于 23 个小格子来说,口算都可以知道:一共10种贴法,如【p1.png所示】
但对于 310 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。
注意:你需要提交的是一个整数,不要填写任何多余的内容(比如:说明性文字)
样例
答案:101466
#include <iostream> #include <stdio.h> #include <string.h> #include <map> #include <algorithm> using namespace std; const int w = 3, h = 10; // 高 、宽 int graph[w][h]; // 墙 int ans = 0; //方案数 map<int, int> Hash; //用此来去重 //检查2x2格子颜色是否相同 bool check_color() { for(int i = 0; i < w; i++) //行 for(int j = 0; j < h; j++) { //列 if(i+1 < w && j+1 < h) { if((graph[i][j]+graph[i][j+1]+graph[i+1][j]+graph[i+1][j+1]) % 4 == 0) return false; //相同 } } return true; //不同 } void fill_with_tile(int x, int y) { if(x>w-1||y>h-1){ return ; } //未访问 ; 每个位置共有两种摆放方式 if(graph[x][y] == -1) { //方式一:横向摆放 前提: 该位置同行的下个格子有空才行 if(y+1 < h && graph[x][y+1] == -1) { // 0:黄色、1:橙色 for(int i = 0; i < 2; i++) { graph[x][y] = i; graph[x][y+1] = i; if(y == h-1) { fill_with_tile(x+1, 0); //铺下一行 } else { fill_with_tile(x, y+1); //铺当前行的下一个格子 } graph[x][y] = -1; graph[x][y+1] = -1; } } //方式二: 纵向摆放 if(x+1 < w && graph[x+1][y] == -1) { // 0:黄色、1:橙色 for(int i = 0; i < 2; i++) { graph[x][y] = i; graph[x+1][y] = i; if(y == h-1) { fill_with_tile(x+1, 0); //铺下一行 } else { fill_with_tile(x, y+1); //铺当前行的下一个格子 } graph[x][y] = -1; graph[x+1][y] = -1; } } } //以访问 else { if(x == w-1 && y == h-1) { //成功铺满 if(check_color()) { //检查2x2格子颜色是否相同 //自编一个哈希函数,为此摆放方式确定一个键值 int ret = 0, bit = 1; for(int i = 0; i < w; i++){ for(int j = 0; j < h; j++) { ret += graph[i][j] * bit; bit *= 2; } } // count()函数返回map中键值等于key的元素的个数。 if(!
1.阿里云云服务器ECS的英文全称是( A)
A. Elastic Compute Service
B. Elastic Compute Server
C. Elastic Container Service
D. Elastic Computer service
2.单机时代,保护电脑安全的主要方式是(C)
A. 防火墙
B. 入侵检测
C. 杀毒软件
D. WAF
3.HTTPS协议在互联网应用中起到的安全作用是(B )
A. 保存到WEB服务器上的数据会自动加密
B. 确保浏览器与WEB服务器之间的数据传输安全
C. 确保WEB服务器端的数据不会被篡改
D. 减少SQL注入的风险
4.WEB2.0时代黑客攻击的主要目标集中在(A )
A. 互联网应用
B. 穿透防火墙
C. 破坏操作系统
D. 计算机硬件
7.云计算的核心思想是将大量用( A)连接的计算资源统一管理和调度
A. 网络
B. 电线
C. 电缆
D. 电话
9.Linux 有哪几部分组成?(ABC)
A. Kernel
B. Shelll
C. 应用程序
D. 虚拟机
10.在计算机逻辑运算中,最基本的逻辑运算是(ABD)
A. 逻辑与
目录
1、简介
2、安装
2.1、Binary
2.2、RPM(RHEL)就是红帽,CentOS就用这个
2.3、DEB(Ubuntu/Debian)
2.4、创建指定的目录并且将下载的安装包上传上去
3、启动MiniO服务
3.1、脚本如下:
4、进入服务
4.1、添加配置文件
1、简介 MinIO是高性能的对象存储,单个对象最大可达5TB。适合存储图片、视频、文档、备份数据、安装包等一系列文件。是一款主要采用Golang语言实现发开的高性能、分布式的对象存储系统。客户端支持Java,Net,Python,Javacript,Golang语言。客户端与服务器之间采用http/https通信协议。
2、安装 MiniO提供Binary、RPM、DEB三种安装方式。此处推荐使用RPM或DEB安装,它会自动帮助你配置systemctl。但实际选择对应的系统安装方式还是二进制都是一样的。
最新的安装方式可以参考:MinIO | 用于创建高性能对象存储的代码和下载内容
2.1、Binary wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio
chmod +x minio
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001"
2.2、RPM(RHEL)就是红帽,CentOS就用这个 dnf install https://dl.minio.org.cn/server/minio/release/linux-amd64/minio-20230518000536.0.0.x86_64.rpm
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password minio server /mnt/data --console-address ":9001"
2.3、DEB(Ubuntu/Debian) wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio_20230518000536.0.0_amd64.deb
dpkg -i minio_20230518000536.0.0_amd64.deb
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password minio server /mnt/data --console-address ":9001"
2.4、创建指定的目录并且将下载的安装包上传上去 [root@localhost minio]# ll 总用量 93772 drwxrwxr-x. 4 es es 41 11月 29 14:23 data drwxrwxr-x.
文章目录 RandomAccessFile学习笔记前言1、RandomAccessFile基本介绍1.1 RandomAccessFile相关基本概念1.2 RandomAccessFile家族体系 2、RandomAccessFile基本使用2.1 RandomAccessFile常用API介绍2.2 RandomAccessFile常用API演示2.3 RandomAccessFile实现断点续传 RandomAccessFile学习笔记 前言 本文将简要介绍RandomAccessFile这个类的使用,主要包括RandomAccessFile相关的一些概念,常见API的使用,如何利用RandomAccessFile实现一个断点续传的效果
1、RandomAccessFile基本介绍 1.1 RandomAccessFile相关基本概念 RandomAccessFile是什么?
RandomAccessFile 是 Java 中用于对文件进行随机访问的类。与普通的输入输出流不同,RandomAccessFile 允许在文件中任意位置读写数据。
RandomAccessFile的作用有哪些?
随机访问:与其他输入输出流不同,RandomAccessFile 允许在文件中任意位置进行读写操作,可以自由地定位文件指针。读写基本数据类型:RandomAccessFile 实现了 DataInput 和 DataOutput 接口,提供了方便的方法用于读取和写入基本数据类型。支持读写字节数组:除了读写基本数据类型外,还可以通过 read(byte[] buffer) 和 write(byte[] buffer) 方法来读写字节数组。支持文件截断:可以使用 setLength(long newLength) 方法来调整文件的长度,将文件截断或扩展为指定的大小。 常见的应用场景是使用 RandomAccessFile 实现断点续传
注意事项:RandomAccessFile只能读写文件(也就是字节数组)类型的数据,并不能读写流类型的数据
RandomAccessFile的四种访问模式
访问模式特点r(read,只读模式)能读文件,不能写文件、持久化rw(read write,读写模式)能读、写文件,不能持久化rws(read write sync,同步读写模式)能读、写文件,每次写操作都会持久化rwd(read write data,同步写模式)能读、写文件,只有在调用close()、getFD().sync()、关闭程序时才进行持久化 “r”(只读模式):使用只读模式打开文件,只能对文件进行读取操作,无法修改文件内容。“rw”(读写模式):使用读写模式打开文件,允许对文件进行读取和写入操作,并且可以修改文件内容。“rws”(同步读写模式):使用同步读写模式打开文件,除了具有读写模式的功能外,还要求每次写入操作都要将数据同步刷新到底层存储介质(如硬盘)。在使用 rws 模式打开文件时,每次进行写入操作时,不仅会将数据写入到内存缓冲区,还会立即将数据刷新到底层存储介质(如硬盘)。这样可以保证数据的持久性,并且在发生系统崩溃或断电等异常情况时,数据不会丢失。由于每次写入操作都要进行磁盘刷新,所以相比于 rwd 模式,rws 模式的写入速度可能较慢。“rwd”(同步写模式):使用同步写模式打开文件,类似于同步读写模式,在使用 rwd 模式打开文件时,每次进行写入操作时,只有将数据写入到内存缓冲区,而不会立即刷新到底层存储介质。只有在调用 close() 方法、显式调用 getFD().sync() 方法或关闭程序时,才会将数据刷新到存储介质。相比于 rws 模式,rwd 模式的写入速度可能稍快,因为不需要每次都进行磁盘刷新。 适用场景说明:
如果文件只需要具有读操作,就使用 r 模式;如果文件既需要读又需要写,同时对持久化没有要求,就可以用 rw 模式;如果文件既需要读又需要写,同时对持久化有要求严格或者是读多写少的情况,推荐使用 rws 模式如果文件既需要读又需要写,同时对持久化有要求不是很严格 或者是 读少写多,推荐使用 rwd 模式 1.
在微信小程序中,实现 ScrollView 滚动到指定位置有多种方法,下面将介绍三种主要的实现方式。
一、使用scroll-top属性实现滚动 通过设置 scroll-view 组件的 scroll-top 属性,我们可以实现滚动到指定位置。以下是具体实现方式:
<scroll-view scroll-top="{{scrollTop}}" style="height: 500px;"> <view style="height: 1000px; background-color: #eee;"></view> </scroll-view> 滚动逻辑:
Page({ data: { scrollTop: 0 }, scrollToLower: function () { this.setData({ scrollTop: 500 }) } }) 在上述代码中,scroll-top是一个动态数据,通过手动改变scroll-top的值来实现滚动。
二、使用scroll-into-view属性实现滚动 除了 scroll-top 属性,还可以使用 scroll-into-view 属性。该属性用于指定子组件的id,当子组件进入可视区域时,scroll-view 会滚动到该位置。以下是实现方式:
<scroll-view scroll-into-view="{{toView}}" style="height: 400px;"> <view id="item1" style="height: 600px; background-color: #bbb;"></view> <view id="item2" style="height: 600px; background-color: #fff;"></view> <view id="item3" style="height: 600px; background-color: #fff;"></view> </scroll-view> 滚动逻辑:
Page({ data: { toView: 'item3' }, scrollToView: function () { this.
在线 SQL 模拟器SQL Fiddle使用简介 本文可作为“SQL语言与SQL在线实验工具的使用” https://blog.csdn.net/cnds123/article/details/115038700 一文的补充。
有时候,我们想去验证 SQL语句,却缺少数据库环境,那该怎么办呢?
这时候在线 SQL 模拟器就有了用武之地。SQL 模拟器免安装,可以在网页直接运行 SQL 。
SQL Fiddle 支持 MySQL、Oracle、PostgreSQL、SQLite、MS SQL Server等主流数据库,不需要注册即可使用。注意,没有缓存功能,关闭窗口后需要重新建表和插入数据。
打开SQL Fiddle 网址http://sqlfiddle.com/ 后,如下图所示:
左边栏用于构建表结构、初始化数据,右边栏放置要执行的 SQL,点击“Run SQL” 按钮就会执行 SQL,结果将在下边输出。
网页上方菜单栏包含一个“MySQL 5.6”下拉框,改下拉框可以选择数据库类型及版本,当前支持的有MySQL 5.6、Oracle 11g R2、Postgr等免费在线SQL数据库。
按钮“View Sample Fiddle”给出和其右边下拉框选定的数据库类型及版本相关的默认示例。
按钮“Clear” 可以清除下面两个面板的输入内容。
左边栏用于构建表结构、初始化数据,右边栏放置要执行的 查询语句。
参见上图,在左边栏输入:
create table students(
id int unsigned primary key,
name varchar(10) not null,
age int(3)
);
INSERT INTO students (id, name, age) VALUES (1, '张三', 20),
(2, '李四', 22),
#创作灵感#
这个错误提示说明你的系统无法找到 php 命令。这可能是因为 PHP 没有正确安装,或者没有将 PHP 的可执行文件路径添加到系统的环境变量中。
要解决这个问题,可以按照以下步骤进行操作:
echo $PATH //显示当前已经配置的环境全局变量 如果输出中没有包含 PHP 的安装路径,那么需要手动将其添加到环境变量中。打开终端配置文件(例如 ~/.bashrc、~/.zshrc 等),并在其中添加以下代码:
export PATH="/path/to/php/bin:$PATH" // 将 /path/to/php/bin 替换为你实际安装 PHP 的路径。 //保存文件后,重新启动终端或执行以下命令使配置生效: source ~/.bashrc // 或 source ~/.zshrc 此处使用的 vi ~/.bashrc,打开发现,环境变量里有其他路径,而打开的是一个空文件,不用管,直接按照方法配置php路径即可
具体找到php路径:
export PATH="/Applications/phpstudy/Extensions/php/php7.3.11/bin:$PATH" //本地环境是phpstudy,找到php的路径 以上路径 写入 vi ~/.bashrc 文件中,保存 //执行命令,使配置生效 source ~/.bashrc 再终端运行 php -v 出现版本信息,即时配置成功,可在任何地方使用
PHP 7.3.11 (cli) (built: Dec 4 2019 11:10:06) ( ZTS ) Copyright (c) 1997-2018 The PHP Group
MobaXterm中文版安装及简单使用 转载地址:https://blog.csdn.net/qq_50119948/article/details/132830080
项目原地址:
https://mobaxterm.mobatek.net/download.html
1.开源中文版 项目地址:
https://github.com/RipplePiam/MobaXterm-Chinese-Simplified?login=from_csdn
本仓库旨在对 MobaXterm Home Edition (Portable edition) 进行简体中文汉化。
不保证实时更新:
汉化最新版本: v0.23.109
进入链接地址,进入【tag】页面,选择版本下载。
下滑到底部,单击下载
2.安装 解压后,直接双击exe
3.简单使用 新建会话
此为登录成功的页面