文章信息
本周阅读的论文是题目为《Meta Graph Transformer: A Novel Framework for Spatial-Temporal Traffic Prediction》的一篇2022年发表在《Neurocomputing》上的使用Transformer进行交通预测的文章。
摘要
精确的交通预测对于提高智能交通系统的性能非常重要。这项任务的关键是在学习和利用交通数据时空异质性的同时,对其复杂动态进行准确建模。本文提出Meta Graph Transformer(MGT)解决这个问题,该模型是对原始Transformer 的改进和推广,原始的Transformer是用于自然语言处理中对向量序列进行建模。具体来说,MGT包含encoder-decoder架构,其中encoder用于将历史交通流数据编码为中间状态,而decoder自回归预测未来交通状态。MGT的主要构建模块为三种类型的注意力层,分别是时间自注意力层(TSA)、空间自注意力层(SSA)以及时间编码-解码注意力层(TEDA),它们均由多头注意力架构组成。encoder和decoder均使用了TSAs和SSAs以捕捉时空相关性。TEDAs被应用于decoder,使decoder中的每个位置与输入序列中的位置一一对应。通过利用多图,SSA可以实现空间注意力的稀疏。为了便于模型对时间和空间条件的感知,从外部属性中学习时空嵌入(STEs),外部属性包括时间属性(序列顺序、时间)和空间属性(如拉普拉斯特征映射)。接着,所有的注意力层通过元学习学习这些映射嵌入,从而赋予注意力层时空异质性感知(STHA)属性。在三个真实交通数据集上的实验表明了MGT的效果优于最先进的方法。
介绍
交通基础设施的发展和人们不断变化的出行需求要求交通资源的有效优化和配置。智能交通系统(ITS)需要解决这些问题。智能交通系统的核心是智能交通基础设施和数据分析算法。前者可以从各种设备(如环路检测器和地铁票价采集系统)收集大量交通数据,而后者在将交通数据转化为有用信息方面起着关键作用。交通预测是ITS系统的基础任务之一,其目的是预测未来交通状态(未来第H个时间步的交通状态)。图1简要说明了时空流量预测。准确的交通预测可以协助交通部门更好地管理与规划,然而复杂的时空相关性使得这项任务具有挑战性。
图1 时空交通流量预测
早期,学者普遍使用统计模型解决交通预测问题,例如基于自回归综合移动平均的方法、卡尔曼滤波器和向量自回归模型,这些模型得到了严格数学理论的验证。然而,这类模型对于交通数据的假设可能不正确(线性、平稳等)。随后,学者提出了各种基于机器学习的交通预测模型,例如支持向量机、随机森林以及k近邻模型。这些模型能够学习非线性依赖关系并提取更复杂的相关性,尤其是在大规模数据情况下。然而这些模型的有效性很大程度取决于复杂的特征工程,不仅耗时而且困难。
近年来,深度学习在多个领域迎来突破,例如图像识别、目标检测等,其强大的能力同样吸引了交通领域的学者。通过将区域划分为网格,2D或者3D(包括时间维度)卷积神经网络可用于交通预测,但这类方法没有考虑交通流数据的拓扑结构。另一个研究方向是时空图神经网络(STGNNs),通过图结构反映交通流数据的空间信息,这类方法在近年非常受欢迎,典型的模型包括STGCN和DCRNN。如名字所示,STGCN通常包括两个部分的建模,一部分为空间维度,另一部分为时间维度,两部分的建模可以分别进行也可以同时进行,后者一种常见的做法就是用图卷积代替循环神经网络(RNN)中的矩阵乘法。STGCN框架面临的主要挑战是有效捕获交通网络演化过程中复杂的时空相关性,从而尽可能提高预测准确性。
就空间相关性建模而言,许多模型基于静态图实现图卷积网络,这种静态图通常是根据实际路网进行搭建,边的权重反映了两个节点在距离方面的接近程度。虽然基于节点距离的图在一定程度上揭示了地理位置相近的节点之间相互影响,但在长期建模中是远远不够的。为了解决该问题,Graph WaveNet和AGCRN提出通过节点嵌入学习隐藏的空间依赖性,而PVCGN和Multi-STGCnet则从多角度构造多图进行空间特性学习。这些方法的问题在于,每个图(预先构建或者学习的)分配给相邻节点的权重在训练后是固定的,并不适用于空间相关性可能随时间变化的交通流任务。因此,部分学者考虑利用注意力机制动态确定邻接的权重。通常来说,邻接节点分配到的注意力系数是通过参数化函数计算的,将目标节点和相邻节点的特征作为输入。通过这种方式,动态权重替代静态权重用于特征聚合从而增强模型适应性。
然而大多数基于注意力机制的方法都有一个显著缺点,即参数在所有位置和时间间隔之间共享,因此节点间的相关性完全取决于各自特征。以图2的地铁站点对为例,站点A位于商业中心而站点B位于居住区。在高峰时段,出行主要以通勤为主,因此站点A的出站流与站点B的进站流存在很强的相关性;相反在非高峰时段,交通流更加随机,导致站点A和站点B之间的相关性较弱。考虑在7:00到14:00的数据对(a, b)和(c, d),前者取自高峰时段而后者则不然。a时刻和c时刻的客流数据保持一致,时刻b和d也是一样,如果相关性仅取决于客流特征,那么时刻a、b的应该分别与时刻c、d相关,但事实并非如此。这表明空间相关性会受到时间变化影响,此外空间相关性还需要考虑空间异质性,因为典型交通网络中不同节点的拓扑结构不同。因此考虑时空异质性是优化空间建模的可选方向。
就时间相关性建模而言,大多数现有方法可以分为三类:基于RNNs的方法;基于CNNs的方法以及基于注意力机制的方法。RNN最早被提出应用于自然语言处理,尝试学习长短时记忆信息,但由于梯度消失问题,RNN实际上难以捕捉长时依赖性,同时RNN的序列模式使模型在训练期间无法并行化。基于CNN的方法沿时间维度采用1D卷积实现并行化。然而,1D卷积受限于卷积核大小无法有效捕捉长时依赖。虽然随着足够多的1D卷积层的堆叠,任何一对时间点最终都会相互关联,但时间点的相关性将被稀释而无法有效利用。相比之下,基于注意力机制的方法通过关注每个时间位置有效学习长时依赖,并且可以实现计算并行化。
正如空间建模一样,可以利用时空异质性来提高时间建模的能力。以图2中(e, b)和(f, d)数据对为例,它们分别具有相同的时间间隔(一小时)和相同的客流数据。由于(e, b)取自高峰时段,它们的相关性会比(f, d)的更加明显,这种差异无法在时空同质的方法中体现。
图2 时空异质性的含义。A和B为两个地铁车站
这篇文章提出了一个深度学习框架,名为Meta Graph Transformer(MGT)以解决交通预测问题。MGT在时间和空间维度充分运用了注意力机制以实现动态联系、高效的长时依赖性建模以及计算并行化等。另外,文章设计了一个元学习过程,将外部时间和空间属性中学习到的元知识整合到注意力层中,从而使模型能够实现时空异质性感知注意。此外,多图结构被整合到模型的空间注意力层中以便考虑各种类型的空间相关性。文章的主要贡献如下:
本文将元学习整合到注意力机制中以捕获交通预测任务中交通流数据的时空异质性。
外部空间和时间属性被融合到空间-时间嵌入模块(STEs)中,在STE指导下,三种类型的注意力层被提出以实现时间和空间维度上的STHA操作。
为了更好地捕捉不同类型的空间依赖性,提出了多图下的空间注意力机制。。
在三个交通数据集上进行了大量实验,以评估文章提出的模型。结果表明,MGT明显优于最先进的模型。
预备知识
Problem Formulation
Definition1 (Traffic Network): 交通网络是一个有向图网络,其中是交通系统中N个节点的集合(例如道路传感器、路段、交叉口节点或者地铁车站节点),E是由多组有序节点对组成的边,例如表示节点i和节点j之间的一条有向边,而A表示邻接矩阵,如下所示:
Definition 2 (Traffic States): 节点i在时间段t的交通状态定义为,其中C表示特征的数量(如速度和流量)。同时将所有节点在时间段t的交通状态定义。
Definition 3 (Temporal Attributes): 每个时间间隔t包含几个时间特征,例如一天中的观测时间、一个星期中观测的天数等。假设有M个有效的时间属性,时间段t中第m个属性定义为,其中表示可能的状态数。
Definition 4 (Multiple Graph): 基于图结构的相关知识,构造多个图结构来解释节点间的不同关系。这些图被定义为,其中是边的集合,是的权重矩阵,B是可行图的数量。所有图共享相同的节点集合V。
Problem. 给定过去P个时间段的历史交通状态:给定过去P个时间段和未来H个时间段的时间特征:以及多重预构建的图,文章的目标是预测未来H个时间段的交通状态:
2. Multi-Head Attention
Android 得到主题中对应的属性的结果或自己设置的style中的结果该文在说GetBag(uint32_t resid, std::vector<uint32_t>& child_resids)的时候,会通过FindEntry(resid, 0u /* density_override /, false / stop_at_first_match /, false / ignore_configuration */)会得到一个ResTable_map_entry结构的数据指针。该指针就是Bag资源在内存中的位置。
我们知道,查找一个资源的时候,是根据一个32位整数来查询的。这个32位整数分成3部分,前8位是包id,系统资源包id是01,应用资源包id是0x7F;接着8位是类型id,类型id是从1开始,所以查找资源的时候,在用做数组序列时,需要先减1;最后16位是对应类型中该资源收集过程中的出现序列,叫entry_idx。
查找资源的过程中,是先通过包id找到对应的包,因为包id不是从0递增,所以需要维护包id与对应数组序列的映射,从下面的代码中可以看出,然后再通过类型id,找到包中对应的类型,最后通过entry_idx找到该类型中对应的资源。
AssetManager2 前面的文章也说了,AssetManager2里面包含着应用所有的资源内容。有必要了解下该类
class AssetManager2 { ………… // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must // have a longer lifetime. std::vector<const ApkAssets*> apk_assets_; // DynamicRefTables for shared library package resolution. // These are ordered according to apk_assets_. The mappings may change depending on what is // in apk_assets_, therefore they must be stored in the AssetManager and not in the // immutable ApkAssets class.
🔥点击进入【硬件安全】社区,查看更多精彩内容🔥
🔥点击查看《AMBA总线》系列文章🔥
📢 声明:
🥭 作者主页:【摆渡沧桑的CSDN主页】。
⚠️ 未经作者允许,禁止转载。
⚠️ 本文为非盈利性质,目的为个人学习记录及知识分享。因能力受限,存在知识点分析不正确的可能。若您参考本文造成了不良后果,本人不承担相关责任。
⚠️ 若本文所采用图片或相关引用侵犯了您的合法权益,请联系我进行删除。
😄 欢迎大家指出文章错误,欢迎同行与我交流 ~
文章目录 一、AHB2APB桥的基本原理1. AHB与APB总线2. AHB与APB总线的特性3. AHB2APB桥的作用(为什么会有桥?)4. SoC系统中的AHB2APB桥所处的位置 二、AHB2APB桥的分类(按照时钟频率来分)1. SoC系统总线的时钟分布2. AHB2APB桥的分类 三、AHB2APB同步桥 (时钟来源、相位相同)——APB使用的时钟和AHB的时钟相同1. 同步桥的优点:2. 同步桥缺点: 四、AHB2APB异步桥(时钟频率、相位可以相同也可以不同)1. 异步桥的优点:2. 异步桥的缺点: 一、AHB2APB桥的基本原理 1. AHB与APB总线 AHB: Advanced High-performance Bus,高级高性能总线
APB: Advanced Peripheral Bus,高级外设总线
2. AHB与APB总线的特性 AHB:
1.高性能、高时钟频率、高带宽
2.多master并行操作、Burst突发操作、split分片传输、2级流水线传输
3.可以作为master接口,也可以作为slave接口
4.CPU、DSP、DMA、FLASH、SRAM等
APB:
1.低速、低带宽
2.设计简单,只有SETUP、ENABLE两个状态
3.专为降低功耗和接口复杂而设计的总线
4.只作为slave属性的外设总线
5.常见的有UART,I2C,SPI,RTC,GRCC,PWM等
3. AHB2APB桥的作用(为什么会有桥?) 1.用于AHB主设备到APB的从设备的连接
2.完成AHB和APB协议的转换、以及异步数据的通信
3.AHB2APB桥是AHB总线上的从设备,也是APB总线唯一一个主设备
4. SoC系统中的AHB2APB桥所处的位置 左边是SoC系统中基本的master,如Cortex M3, 通过matrix仲裁器会将总线地址,分别映射到AHB的slave中,
中间通过两个bridge(外设众多,可以通过两组bridge来管理不同外设),AHB将与APB上的从设备通信
二、AHB2APB桥的分类(按照时钟频率来分) 1. SoC系统总线的时钟分布 SOC系统中时钟来源很多,如对于RTC,WatchDog等外设,对于时钟频率的要求很低(32.
这个简单,就不长篇大论了。
打开vs,点开目标文件,看一下右下角你就知道该点哪里了。
但是警告!!!,在进行这个操作时请先把原来代码的中文字符复制下来,否则编码一改你原来的中文字符就会乱码
很简单,点红圈位置
上面就会出现这两个。
一、场景还原 现在假定有如下html代码:
<div class="content"> <p>输入只有一行半径r.</p> </div> <div class="content"> <p>输出有多行,每一行是跟输入对应面积.</p> <p>输出保留6位小数</p> </div> 我需要获取每个content下的所有子节点的文本。形如这样
['输入只有一行半径r.', '输出有多行,每一行是跟输入对应面积. 输出保留6位小数']
二、解决方案 代码如下:
from lxml import etree txt = """ <div class="content"> <p>输入只有一行半径r.</p> </div> <div class="content"> <p>输出有多行,每一行是跟输入对应面积.</p> <p>输出保留6位小数</p> </div> """ html = etree.HTML(txt) contents = html.xpath('//div[@class="content"]') lst = [] for e in contents: lst.append(e.xpath('string(.)')) print(lst) ''' 输出如下: ['\n 输入只有一行半径r.\n', '\n 输出有多行,每一行是跟输入对应面积.\n 输出保留6位小数\n'] ''' 其实这已经和我们想要的结果差不多了,对字符串稍作处理就是我们想要的结果了
from lxml import etree txt = """ <div class="content"> <p>输入只有一行半径r.</p> </div> <div class="
一、基本查询语法 1、查询所有结果
GET /es_test_20211119/_search {"query":{"match_all":{}}} 2、根据条件查询
GET /es_test_20211119/_search { "query": { "match": { "_cw_line_num": "27,28" } } } 3、排序
GET /es_test_20211119/_search { "query": { "match": { "_cw_line_num": "27,28" } } } 4、指定返回_source指定的字段
{ "query": { "match_all": {} }, "_source": [ "_cw_log_type" ] } 5、批量查询
{ "query": { "_cw_line_num": { "values": [ 27, 28 ] } } } 6、单索引批量查询
{ "ids": [ "1001", "1002", "1003" ] } 7、term不分词查询
{ "query": { "
群里一直有小伙伴,不知道咋下载某鹅通的视频,这里说一下我的逆向过程(开始那个某利威的确实不怎么详细,逻辑也很胡乱,主要是我不知道有挺多小伙伴需要这个,我当时就随便写写,记录一下,也没想有多少人看)
1.首先找m3u8链接 这里我们直接抓包,可以看到,这个m3u8链接
这个抓包过程就不赘述了,我们看一下这个m3u8的返回。
可以看到,这个返回的是一串字符,看来是加密的。
2.寻找解密代码 这个m3u8文本是加密的,但是他肯定要解密后才能进行解析,所以,我们要找到他的解密代码。这里对这个m3u8解密视频的key下一个断点。
就是这个链接。
查看一下他的发起程序。
可以看到一个loadkey,既然已经loadkey了,那肯定在这个之前就已经解密完成了,我们再往下移一下看看。
可以看到这个loadsuccess,这个很可疑。点进入看一下。
可以看到这样的代码,很熟悉,应该是对m3u8文件进行解析。看来解密不远了。先打结果断点。断住看看。
断住过后,找到这个解密函数,是这个D.decrypt,输出一下这个t.data。可以看到。
就是没解密的数据,而 D.decrypt(t.data)就是解密后的数据。
3.进入D.decryp函数 进入到decrypt函数,可以看到这些东西,乍一看,人都麻了,这一定是混淆了吧?头都大了,殊不知,这都是障眼法。他是直接运行了这样一行代码。
return t[y[1] + m[54] + y[9] + y[32] + y[26] + m[50] + y[10]](y[24] + v[50] + v[2]) > -1 ? (t = (t = (t = (t = (t = t[y[27] + m[34] + v[29] + y[58] + m[58] + y[30] + y[32]](m[27] + m[42] + v[2], ""))[y[27] + y[32] + m[17] + y[58] + m[58] + y[30] + m[34]](/@/g, y[35]))[m[60] + y[32] + y[19] + m[55] + y[12] + y[30] + y[32]](/#/g, m[44]))[m[60] + m[34] + v[29] + m[55] + v[2] + y[30] + v[8]](/\$/g, y[48]))[v[58] + v[8] + y[19] + v[53] + m[58] + y[30] + v[8]](/%/g, v[11]),I(O(t))) : t return了一个值,判断ty[1] + m[54] + y[9] + y[32] + y[26] + m[50] + y[10]是否大于-1,如果不大于,就直接返回t,大于则执行,
插件版本所需的 Gradle 版本1.0.0 - 1.1.32.2.1 - 2.31.2.0 - 1.3.12.2.1 - 2.91.5.02.2.1 - 2.132.0.0 - 2.1.22.10 - 2.132.1.3 - 2.2.32.14.1 - 3.52.3.0+3.3+3.0.0+4.1+3.1.0+4.4+3.2.0 - 3.2.14.6+3.3.0 - 3.3.34.10.1+3.4.0 - 3.4.35.1.1+3.5.0 - 3.5.45.4.1+3.6.0 - 3.6.45.6.4+4.0.0+6.1.1+4.1.0+6.5+4.2.0+6.7.1+7.07.0+7.17.2+7.27.3+
前言 本文源码大部分是采用的OpenCV实战(一)——简单的车牌识别这篇文章所提供的代码,对其代码进行了整合,追加了HSV、tesseract-OCR等内容。大佬文章中有对其步骤的详细讲解和分析,本文只是在原有基础上,进行了拓展和改造,细节内容可直接参考大佬的博文。由于大佬没有提供完整项目和模型,我这进行了自己简单的数据集构建和模型训练。
Windows tesseract-OCR 的安装和简单测试
ps:所有图片素材均源自网络,如果侵权可私信,立删。
开发环境:
pycharm-2020python-3.8.5opencv-python-4.5.4.58matplotlib-3.5.0pip-21.2.3Tesseract-OCR-5.0.0numpy-1.21.4sklearn-0.0.0joblib-1.1.0
工程下载 码云 github
效果图 简易流程图 源码 import cv2 import numpy as np import matplotlib.pyplot as plt import os import time import sklearn # import pytesseract # 开发环境 pycharm python-3.8.5 opencv-python-4.5.4.58 matplotlib-3.5.0 pip-21.2.3 Tesseract-OCR-5.0.0 # 参考:https://blog.csdn.net/weixin_41695564/article/details/79712393 # 该函数能够读取磁盘中的图片文件,默认以彩色图像的方式进行读取 def imread_photo(filename, flags=cv2.IMREAD_COLOR): """ 该函数能够读取磁盘中的图片文件,默认以彩色图像的方式进行读取 输入: filename 指的图像文件名(可以包括路径) flags用来表示按照什么方式读取图片,有以下选择(默认采用彩色图像的方式): IMREAD_COLOR 彩色图像 IMREAD_GRAYSCALE 灰度图像 IMREAD_ANYCOLOR 任意图像 输出: 返回图片的通道矩阵 """ return cv2.imread(filename, flags) # 等比缩放 参考:https://blog.csdn.net/JulyLi2019/article/details/120720752 def resize_keep_aspectratio(image_src, dst_size): src_h, src_w = image_src.
脑子抽筋尝试在vs 2022 for mac 版本中编写Mvc应用,真是踩的一堆坑,试了大半天终于将mysql数据库连接配置完成,(基于code firts)
---------------------------环境------------------------------
操作系统:macOS monterey 12.1(M1)
mysql数据库:8.0.28-arm64
开发工具:Visual Studio 2022 for Mac (Preview)(尝鲜。。。bug真多一言难尽哈哈哈哈)
---------------------------------------------------------------
开始溜达起来:
一、创建.NET6 MVC应用
二、导入相关NuGet包
Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Tools Pomelo.EntityFrameworkCore.MySql 三、配置数据连接并迁移
(1)构造数据连接类
新建Data文件夹->文件夹中新增空白类->添加如下代码
using System; using Microsoft.EntityFrameworkCore; namespace EFdome.Data { //原始生成的类代码 //public class MyDbContext //{ // public MyDbContext() // { // } //} //手动改造后的类代码 public class MyDbContext:DbContext { public MyDbContext(DbContextOptions<MyDbContext> options):base(options) { } } } (2)修改appsettings.json配置类
增加ConnectionStrings
{ "Logging": { "LogLevel": { "Default": "Information", "
命名空间,文件夹称为包
但在uml中包是1.表达体系结构,2.就是针对类(业务实体类,控制管理类)的划分
主要作用就是对类的逻辑划分。与命名空间概念类似。
uml2.0后包中只建议包含类或其他的包。同级包名不能冲突
use import直接将包引进了进来,use再设计期使用,import在实现时使用。是全部引入。
access并不引入包,只是部分引入。
整体划分,体系结构
充分采用重用构建体系。
分离法用的最多。
业务逻辑层与数据访问层一般放在服务端。层状模式。
物理建模(真实存在的东西,比如文件或程序包)的两大视图:组件图,部署图。
软件代码其实指的是文件。作为文件来说是物理模块。
组件可以看做是大的容器,里面包含大量的类。
源码结构,调用关系
一,Dijkstra算法 1,初始化:先找出从源V0到各终点Vk的直达路径(V0,Vk),即通过一条弧到达的路径.如果一条弧不能到达的点记为 无穷大
2,选择:从这些路径中找出一条长度最短的路径(V0,U).
3,更新:然后从其余各条路径进行适当调整:
若在图中存在弧(U,Vk),且(V0,U) + (U,Vk) < (V0,Vk),则以路径(V0,U,Vk)代替(V0,Vk)
4,在调整后的各条路径中,再找长度最短的路径(依此类推).
具体的操作为:
1,把V(顶点)分成两组:
(1)S:已求出最短路径的顶点集合.
(2)T = V - S:尚未确定最短路径的顶点集合.
2,将T中顶点按最短路径递增的次序加入到S中.
要保证: (1)从源点V0到S中条顶点的最短路径长度都不大于从V0到T中任何顶点
的最短路径长度.
(2)每个顶点对应一个距离值:
S中顶点:从V.到此顶点的最短路径长度
T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度.
举个例子:
最终:S = {a, b, c, d, e, f},T={}.
a到各顶点间的最短路径为:ab = 3, ac = 4, ad = 7, ae = 11, af = 15.
二,以上面的例子,代码的实现 #include <stdio.h> #include <stdlib.h> #define MAXSIZE 10 #define MAXINT 10000 typedef struct{//表示顶点,包含名称和权重 char data; int weight; }vertex; typedef struct{//表示顶点集合,包含顶点数组和顶点个数 vertex arr[MAXSIZE]; int size; }VertexSet; int get_index(VertexSet a, char b)//根据输入顶点的名称,得到该顶点在数组中的下标 { int i = 0; for(i = 0; i < a.
1.removeAbandoned如何排查连接泄露 1.1 什么是连接泄露 连接池中连接数同一时间被用光(长SQL、连接执行完成后没有及时归还等均有可能造成),超过获取连接最大等待时间后仍然没有获取到连接。
1.2 如何通过removeAbandoned排查连接泄露 通过开启removeAbandoned参数,使其在每次获取连接时记录当前线程的堆栈信息。
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException { ···省略部分代码··· //判断是否开启removeAbandoned if (removeAbandoned) { //记录当前线程的堆栈信息(此操作很耗时) StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); poolableConnection.connectStackTrace = stackTrace; //记录连接开始时间 poolableConnection.setConnectedTimeNano(); //设置开启跟踪,设置后将在归还连接时清除当前连接的活跃状态 poolableConnection.traceEnable = true; //获得锁,向activeConnections中置入连接对象 activeConnectionLock.lock(); try { activeConnections.put(poolableConnection, PRESENT); } finally { activeConnectionLock.unlock(); } } ···省略部分代码··· return poolableConnection; } } 开启logAbandoned参数,使其能够在回收时将当前堆栈信息进行打印。
//如果开启了logAbandoned,则拼接日志并进行输出 if (isLogAbandoned()) { //拼接异常堆栈信息 StringBuilder buf = new StringBuilder(); buf.append("abandon connection, owner thread: "); buf.append(pooledConnection.getOwnerThread().getName()); buf.append(", connected at : "
一、问题的出现 使用Thonny运行pico代码时,出现了报错,是我们常见的ImportError:no moudel named …
所以这种情况很简单,去import这个modulde就OK了。
Thonny中【工具】→【管理包】,去搜索我们需要安装的包即可。
却出现了报错:
问题1:
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1091)
问题2:
During handling of the above exception, another exception occurred:
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1091)>
minipip returned with error code 1
问题的关键还是在于CERTIFICATE_VERIFY_FAILED。
让我们再仔细看一下报错的文件位置,位于urlib的request.py中:
二、问题的解决 很简单,首先根据位置找到那个文件:
打开它:
感谢 真·skysys 大佬的方法,根据这篇文章,我们只要在代码中加入即可:
import ssl # 导入证书模块 ssl._create_default_https_context = ssl._create_unverified_context # 在加上这段即可解决 找个位置加上代码后:
问题成功解决,module顺利安装。
假设张家界景区的游客抵达检票口的速度是恒定的。某国庆长假日清晨景区开门时检票口已积聚了一定数量的游客,且随时间流逝,不断有新的游客抵达。如果打开8个检票口,m分钟刚好可以完成全部游客的检票放行;如果使用6个检票口,则需要n (n>m)分钟才能完成。请编程计算:如果使用10个检票口,需要多少时间才能将景区入口的待检票人数清零?
【分析】
这是小学奥数中著名的“牛吃草”问题。现假设每个检票口每分钟可以完成1份游客的检票放行任务。设景区开门时积聚的游客数量为x份,设每分钟有y份游客抵达检票口。然后列出方程组,根据方程组求解x,y。
然后,设使用10个检票口时,需要z分钟清零,根据x,y列方程,求出z。
输入格式: m
n
说明:m,n为整数且n>m,且该输入确保问题有解。
输出格式: 原有排队游客份数:A, 每分钟新到游客份数:B, 10口同开需C分钟清零待检票游客.
说明:A, B, C均为保留1位小数的浮点数。
输入样例: 180 300 输出样例: 原有排队游客份数:900.0, 每分钟新到游客份数:3.0, 10口同开需128.6分钟清零待检票游客. m=int(input())
n=int(input())
y=(6*n-8*m)/(n-m)
x=m*(8-y)
z=x/(10-y)
print("原有排队游客份数:{:.1f}, 每分钟新到游客份数:{:.1f}, 10口同开需{:.1f}分钟清零待检票游客.".format(x,y,z))
前言: pip 是一个现代的,通用的 Python 包管理工具。提供了对 Python 包的查找、下载、安装、卸载的功能。注:pip已内置于Python3.4和2.7及以上版本,其他版本需另行安装
Python3包管理pip命令: 1、安装第三方库
前置:在windows系统下,进入cmd.exe
pip install package_name
pip install package_name==版本号 安装指定版本的包
pip isntall package_name - i https://pypi.douban.com/simple/ 使用国内源(豆瓣)安装第三方库
2、卸载
pip uninstall package_name
3、升级
pip install -U package_name
pip install -U package_name==版本号 升级到指定的版本
4、查看目前安装了哪些库
pip list
5、升级pip命令
python -m pip install --upgrade pip
6、虚拟环境相关命令
本地环境:安装的包都在本地,所有的项目都可以共享使用
虚拟环境(做项目开发,测开项目):只针对某一个项目使用的环境
pip freeze > packages.txt
pip install -r packages.txt Dockerfile来完成
7、在python目录下查看已安装的包
——打开下载python的文件夹——找到Lib页面
——查看Lib页面中已下载的包
————————————————
常用国内源:
1 豆瓣(douban) https://pypi.douban.com/simple
2 清华大学 https://pypi.
目录
DNS介绍:
开始搭建
第一步:建立两个CentOS 7虚拟机(网络为仅主机模式,用最小安装就可以了)
第二步:配置yum源,网卡
主服务器
从服务器
第三步:安装、修改DNS文件
主服务器
设置正反解析文件
从服务器
搭建完成
DNS介绍: 相对于数字构成的IP地址,域名更好被理解和记忆,就像我们通常输入域名来访问一个网络中的资源。(如www.csnd.net;39.106.226.142)
但是网络中的计算机只能用IP地址来相互识别身份,传输数据也一样,只能依靠外网的IP来完成。
为了降低用户访问网络资源的门槛,DNS(域名系统)技术应运而生
这是一项用于管理和解析域名和IP地址对应关系的技术。简单来说,就是能够接收用户输入的域名或IP地址,然后自动查找与之匹配的IP或者域名
可以理解为这个服务使域名和IP地址形成了一个映射关系,这里也要介绍两种DNS的两种解析方式
正向解析:将域名解析成IP地址(这也是我们最常用的,输入网址访问网页,系统根据域名映射的IP去查找相应的网站,然后访问)
反向解析:将IP地址解析为域名
域名后缀一般分为国际域名和国内域名。
这里介绍集中最常见的域名
.com(商业组织) .org(非营利组织) .gov(政府部门).net(网络服务商) .edu(教研机构)
.pub(公共大众) .cn(中国国家顶级域名)
为了维护网络提供不间断、稳定且快速的域名查询服务,保证互联网的正常运转,下面介绍主要的三种服务器
三种类型的服务器:
主服务器:在特定区域内具有唯一性,负责维护该区域内的域名与IP地址之间的对应关系。
从服务器:从主服务器中获得域名与IP地址的对应关系并进行维护,以防主服务器宕机(可以理解为无法恢复的死机)等情况
缓存服务器:主机向其他域名解析服务器查询获得域名与IP地址的对应关系,并将经常查询的域名信息保存到服务器本地,以此来提高重复查询时的效率
简单来说
主服务器就是用于管理域名和IP地址对应关系的真正服务器。
从服务器是帮助主服务器“打下手”,它分散部署在各个国家、省市或地区、以便让用户就近查询域名,从而减轻主服务器的负载压力
缓存服务器不太常用,一般部署在企业内网的网管位置,用于加速用户的域名查询请求DNS域名解析服务采用分布式的数据结构来存放海量的“区域数据”信息,在执行用户发起的域名查询请求时,一般采用递归查询和迭代查询两种方式
递归查询:DNS服务器在收到用户发起的请求时,必须向用户返回一个准确的查询结果,如果DNS服务器本地没有没有储存与之对应的信息,则该服务器需要询问其他服务器,并将返回的查询结果提交给用户。
迭代查询:DNS服务器在收到用户发起的请求时,并不直接回复查询结果,而是告诉另一台DNS服务器的地址,用户再向这台DNS服务器提交请求,这样一次反复,直到返回查询结果(个人觉得这个查询的应该更准确,它把每一次查询的结果作为下一次查询的条件)
开始搭建 搭建目的:
主从服务器都可以双向正反解析
第一步:建立两个CentOS 7虚拟机(网络为仅主机模式,用最小安装就可以了) 第二步:配置yum源,网卡 主服务器 配置网卡
[root@localhost~]# vi /etc/sysconfig/network-scripts/ifcfg-ens33 //进入网卡配置文件
BOOTPROTO=static //修改IP获取方式(这里改成静态)
ONBOOT=yes //打开这个网卡
在下面新增
IPADDR=192.168.10.100 //IP地址
NETMASK=255.255.255.0 //子网掩码
GATEWAY=192.168.10.254 //网关敲一样就好
DNS1=192.168.10.100 //DNS设置成自己
:wq
[root@localhost~]# systemctl restart network //重启网卡,没报错就OK了
Druid连接的创建时点
1. initialSize>0时,将在init()时进行创建,此时创建连接由是否指定asyncInit参数来判断,需要注意的是,此时如果采用异步创建需要设置线程池,否则即使开启asyncInit也依旧会采用同步创建。
2. 开启keepAlive并且initialSize<minIdle,将在init()时进行创建,此时将采用异步方式创建连接
3. 抛弃连接(discardConnection)且连接池中活跃连接总数<最小数量,此时采用异步方式创建连接
4. 连接池取出的连接发生异常且fatalErrorCount - fatalErrorCountLastShrink > onFatalErrorMaxActive时,此时采用异步方式创建
5. 从连接池中取连接时,连接池中没有空闲连接,此时将采用异步方式创建连接
6. 向连接池中置入连接时(要求此时为异步线程池方式创建),且满足poolingCount + createTaskCount < notEmptyWaitThreadCount && activeCount + poolingCount + createTaskCount < maxActive时
7. 连接池收缩(shrink)后,将keepAliveConnections归还至池子中时存在校验异常的连接,并且连接池中活跃连接总数<最小数量,此时采用异步创建
8. 连接池收缩后,开启keepAlive且连接池中活跃连接总数<最小数量,此时将采用异步方式将连接池中连接填充至最小连接数
9. 连接池收缩后,未开启keepAlive或连接池中活跃连接总数>=最小数量,并且满足onFatalError || fatalErrorIncrement > 0,此时将采用异步方式创建连接
10. 获得连接时,满足设置了创建线程池、池中没有连接、活跃连接数<最大活跃数、没有创建中的连接、线程池是ScheduledThreadPoolExecutor或它的子类,且此时线程池中存在排队,同步创建
11. 在手动调用fill()方法时,采用同步方式创建
目录
一、ref
二、isRef
三、unref
四、toRef
五、toRefs
六、customRef
七、shallowRef
八、triggerRef
一、ref 接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。
1.简单示例:
<template> <div> 1.simpleRef value:{{simpleRef}} <button @click="handleSimpleRef">点击+1</button> </div> </template> <script setup lang='ts'> import {simpleRef, handleSimpleRef} from './simpleRef'; </script> <style> </style> //simpleRef.ts // 引入ref import {ref} from 'vue'; // 初始化ref const simpleRef = ref(0); // 使用.value获取以及更改ref的值 const handleSimpleRef = ()=>{ simpleRef.value++; } // 导出 export { simpleRef, handleSimpleRef } 2.ref定义复杂结构。但是一般通过reactive处理复杂解构数据。
// 初始化ref const simpleRef = ref({ obj:{ name:'hxshen' } }); // 使用.
自定义消息id
#define WM_MSG WM_USER+100 绑定消息函数
ON_MESSAGE(WM_MSG, OnMsg) 实现onMsg函数
LRESULT CTestLogDlg::OnMsg(WPARAM wP, LPARAM lP) { CString str; MYMSG* mymsg = (MYMSG*)(lP); str.Format(L"%s\r\n", mymsg->str); m_logshow.ReplaceSel(str); return 0; } 其中MYMSG是我自定义的消息结构体
typedef struct mymsg { int msgid; CString str; }MYMSG; 下面进行调用
void CTestLogDlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 static int index = 0; m_logstr.Format(L"ssssss%d",index); index++; showlog(m_logstr); } void CTestLogDlg::showlog(CString str) { MYMSG * mymsg = new MYMSG; mymsg->msgid = 1; mymsg->str = str; ::PostMessage(::AfxGetMainWnd()->m_hWnd, WM_MSG, 0, (LPARAM)mymsg); } 其中log显示框属性如下所示
一、CommonJS的导入导出 1、使用exports导出(注意是有s)
(1)注意:exports刚开始是一个空对象,我们可以在这个对象中添加很多个属性,添加的属性会被导出;
//这是 main.js文件 let name = 'miracle'; let age = 18; function abc() { console.log('你好'+name); } exports.name = name; exports.age = age; exports.abc = abc; (2)另外一个文件中可以导入:
//这是bar.js文件 const bar = require('./main.js'); (3)上面导入那行完成了什么操作呢?
1)意味着bar.js文件中的bar变量等于exports对象;
2)也就是require通过各种查找方式,最终找到了exports这个对象;
3)并且将这个exports对象赋值给了bar变量;
4) bar变量就是exports对象了
(4)注意:bar.js文件中的bar变量是exports对象引用赋值,所以在bar.js文件中修改bar变量的属性值,则exports中对应的属性值也会跟着变化,例如:
//这是main.js文件 let name = 'miracle'; let age = 18; exports.name = name; exports.age = age; //这是bar.js文件 const bar = require('./main.js'); console.log(bar);//第一次输出bar bar.name = 'abc'; console.log(bar);//第二次输出bar //控制台输出的结果 { name: 'miracle', age: 18 } { name: 'abc', age: 18 } 2、使用module.
今天在写Python代码的时候遇到了这么一个小问题,在网上查了也没有一个明确的解答,通过自己的摸索,终于找到问题的所在,真的是一个小问题就能难到很多人,希望能对你们有所帮助。主要还是运算符理解的不够透彻,对于那些学习了很多种编程语言的我们,很容易混淆。
Python位运算符 Python逻辑运算符 首先看编码:
如果我没记错在java中可以使用&&进行逻辑判断,但是在Python中不能这样判断,会出现TypeError: unsupported operand type(s) for &: 'float' and 'float'。
这是因为在Python中位运算符和逻辑运算符是两个概念。所以在进行逻辑比较的时候只能使用逻辑运算符。
修改后的代码:
论文标题:Graph Neural Networks in Recommender Systems: A Survey
发表于:2021 ACM Computing Surveys (CSUR)
作者:SHIWEN WU, FEI SUN, WENTAO ZHANG, BIN CUI
论文地址:https://arxiv.org/pdf/2011.02260.pdf
摘要 能够自然融合节点信息和拓扑结构的图神经网络(GNN)技术引起了广泛关注。在推荐系统中,主要挑战是从交互和辅助信息(如果有的话)中学习有效的用户/项目表示 介绍 推荐系统中的主流建模范式已经从邻域方法 [3、35、64、89] 发展到基于表示学习的框架 [13、50、51、90、110]。
基于项目的邻域方法 [3, 64, 89] 直接向用户推荐与他们交互过的历史项目相似的项目。
通过直接使用他们的历史交互项目来表示用户的偏好 基于表示学习的方法,尝试将用户和项目编码为共享空间中的连续向量(也称为嵌入),从而使它们直接可比较。
从矩阵分解 [50, 51] 到深度学习模型 [13, 33, 90, 153],已经提出了各种方法来学习用户和项目的表示,以更好地估计用户对项目的偏好。 推荐应用程序中的交互数据可以由用户和项目节点之间的二分图表示,观察到的交互由链接表示。甚至用户行为序列中的项目转换也可以构建为图。当结合结构化的外部信息(例如,用户之间的社交关系 [17, 132] 和与项目相关的知识图谱 [113, 150])时,将推荐公式化为图上的任务的好处变得尤为明显。通过这种方式,GNN 提供了一个统一的视角来对推荐系统中丰富的异构数据进行建模。
GNN的优势:
提供一个统一的框架来对推荐应用程序中的大量数据进行建模与仅隐式捕获协作信号(即使用用户-项目交互作为模型训练的监督信号)的传统方法不同,GNN 可以自然而明确地将关键协作信号(即拓扑结构)编码为改进用户和项目的表示早期的工作,例如 SVD++ [49] 和 FISM [43],已经证明了交互项目在用户表示学习中的有效性。鉴于用户-项目交互图,这些先前的工作可以看作是使用一跳邻居来改进用户表示学习。 GNN 的优势在于它提供了强大且系统的工具来探索多跳关系, 工作贡献 新分类。提出了一个系统的分类模式来组织现有的基于 GNN 的推荐模型。 首先根据他们处理的任务将现有作品分为一般推荐和顺序推荐。然后,进一步将这两个任务中的现有模型分为三类:仅交互信息、社交网络增强和知识图增强。 全面审查。对于每个类别,展示了要处理的主要问题。简要介绍了代表性模型并说明它们如何解决这些问题。未来研究。讨论了当前方法的局限性,并提出了六个潜在的未来方向 背景和分类 推荐系统:两种基本类型的任务,从配对交互中建模用户的静态偏好或从顺序行为中建模用户的动态偏好。 一般推荐 通常假设用户具有静态偏好,并基于隐式(例如,点击、阅读或购买)或显式(即,评分)反馈对其进行建模。通用推荐模型的一个常见范式是通过用户和项目的表示来重构用户的历史交互问题描述: 给定用户集 U,项目集 I,以及观察到的用户和项目 R 之间的交互:U×I,对于任何用户表示 h u ∗ ℎ^∗_u hu∗ 和项目表示 h i ∗ ℎ^∗_i hi∗ y u , i = f ( h u ∗ , h i ∗ ) y_{u,i} = f(ℎ^∗_u,ℎ^∗_i) yu,i=f(hu∗,hi∗)评分函数f(·)可以是点积、余弦、多层感知等, y u , i y_{u,i} yu,i表示用户u对项目i的偏好得分,通常以概率表示 研究现状 早期研究以矩阵的形式考虑用户-项目交互,并将推荐制定为矩阵完成任务[52]。 矩阵分解 (MF) 将用户和项目投影到共享向量空间中,以重建整个用户-项目交互矩阵,即估计用户对其未见项目的偏好 [52、54、87]。 最近的深度学习工作,其中一项研究旨在通过将辅助信息与深度学习的力量相结合来提高推荐性能, 例如文本 [47, 110] 和图像 [44, 115]。 另一个研究方向试图使用更强大的模型架构来代替传统的矩阵分解,多层感知机MLP[33]和自动编码[90, 138] 顺序推荐 旨在通过探索她/他的历史交互中的顺序模式来预测用户可能与之交互的连续项目根据用户是否匿名以及行为是否被细分为会话,该领域的工作可以进一步分为顺序推荐和基于会话的推荐 基于会话的推荐可以被视为具有匿名和会话假设的顺序推荐的子类型[84]。 在顺序推荐中,用户的历史交互按时间顺序组织成序列。我们用 s u s^u su = [ i s , 1 , i s , 2 , .
build-tools: aapt: aapt(Android Asset Packaging Tool)即Android资源打包工具,是一款运用于android SDK的反汇编工具,具有apk编译、反编译、分析等功能。可查询apk sdk版本信息等。
使用 配置环境变量:
export PATH=${PATH}:${ANDROID_HOME}/build-tools/30.0.3
aapt l[ist] [-v] [-a] 文件名.{zip,jar,apk}
aapt.exe list -a someapk.apk > apkversion.txt
项目是基于SSH框架的一个老项目,运行平稳由于把服务从本地服务器迁移到阿里云服务器,在迁移的过程中遇到了如下问题:
java.lang.SecurityException: class "org.eclipse.core.runtime.Preferences"'s signer information does not match signer information of other classes in the same package at java.lang.ClassLoader.checkCerts(ClassLoader.java:952) at java.lang.ClassLoader.preDefineClass(ClassLoader.java:666) at java.lang.ClassLoader.defineClass(ClassLoader.java:794) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2818) at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1148) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1643) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:800) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2818) at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1148) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1643) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521) at org.apache.catalina.startup.ContextConfig.checkHandlesTypes(ContextConfig.java:1969) at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:1932) at org.apache.catalina.startup.ContextConfig.processAnnotationsJar(ContextConfig.java:1826) at org.apache.catalina.startup.ContextConfig.processAnnotationsUrl(ContextConfig.java:1785) at org.apache.catalina.startup.ContextConfig.processAnnotations(ContextConfig.java:1771) at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1254) at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:881) at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:316) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:89) at org.
Open3D的基本使用 前言 在处理点云数据时,PCL库的安装和上手难度较大,英特尔的Open3D在性能和开箱即用上表现优异,可以读存、处理和显示各类点云,故做此试验。
准备工作 安装 使用window11下的pychram,配置python3.6的虚拟环境,(PS:open3d到博客写作日期为止,暂时只支持3.6-3.8版本),进行虚拟环境的setting,依次安装open3d,numpy,opencv(optional)
测试数据下载 在gethub上下载open3d的源码,里面包含了我们需要官方提供的测试数据:
isl-org/Open3D: Open3D: A Modern Library for 3D Data Processing (github.com)
测试数据位于:
Open3D-master\\examples\\test_data\\ 初步使用 点云显示 简单的使用,显示一个带彩色的点云
import open3d as o3d import numpy as np print("Load a ply point cloud, print it, and render it") #读取点云数据 pcd = o3d.io.read_point_cloud("C:\\Document\\Open3D-master\\examples\\test_data\\fragment.ply") print(pcd) print(np.asarray(pcd.points)) #显示点云数据 o3d.visualization.draw_geometries([pcd], zoom=0.3412, front=[0.4257, -0.2125, -0.8795], lookat=[2.6172, 2.0475, 1.532], up=[-0.0694, -0.9768, 0.2024]) 显示效果如下所示:
在这里插入图片描述
voxel降采样 voxel降采样使用常规体素栅格从输入点云创建均匀下采样点云。通常用于许多点云处理任务的预处理步骤。该算法分两步操作:
1.点被折成voxel。
2.每个占用的体素通过平均内部的所有点生成恰好一个点。
代码在刚才的基础上稍作改动:
import open3d as o3d import numpy as np print("
CeresSolver采用稀疏矩阵求解大规模BA时参数块设定 前言 在大规模BA求解中,通常会关注到相机位姿与路标参数构成矩阵的稀疏性,将相机位姿参数与路标点参数分组,采用舒尔补充等方法进行消元求解数据量大的组别,提升求解效率,具体可以参考ceres的LinearSolver¶部分。
在实际使用中,构造代价函数时需明确哪些参数为路标点参数,需要被消去;哪些参数为相机参数,首先求解,相当于将参数分组,并决定其消去的顺序。ceres内置了自动分组的方法,但有时不能奏效,此时就需要我们手工指定参数块的分组,并且来决定参数被消去的顺序。
CeresSolver教程相关说明 Ordering¶ The order in which variables are eliminated in a linear solver can have a significant of impact on the efficiency and accuracy of the method. For example when doing sparse Cholesky factorization, there are matrices for which a good ordering will give a Cholesky factor with O(n) storage, where as a bad ordering will result in an completely dense factor.
线性解算器中变量的消除顺序对方法的效率和准确性有重大影响。例如,在进行稀疏Cholesky分解时,对于某些矩阵,良好的排序将给出具有O(n)存储的Cholesky因子,而糟糕的排序将导致完全稠密因子。
Ceres allows the user to provide varying amounts of hints to the solver about the variable elimination ordering to use.
1.Mac下配置ADB 第一步:cd ~/
第二步:touch .bash_profile(创建 .bash_profile,若已经存在该步可省略)
第三步:open .bash_profile
添加如下:
export ANDROID_HOME=/Users/xxx/Library/Android/sdk
export PATH=${PATH}:${ANDROID_HOME}/platform-tools;
export PATH=${PATH}:${ANDROID_HOME}/tools;
其中ANDROID_HOME是自己的SDK所在路径
第四步:source .bash_profile(对修改保存)
配置完成输入:adb
配置成功。
2.adb 找不到连接设备 1.打开终端,输入:system_profiler SPUSBDataType,查看需要添加的USB设备信息,记下相应的厂商Vender ID。
2.执行命令:open -e ~/.android/adb_usb.ini
3.adb_usb.ini文件里添加设备Vender ID,如:
0x05ac
0x12d1
4.重启adb server进程
adb kill-server
adb start-server
即可。
3.adb和adb shell常用命令 查看Android设备版本
adb shell getprop ro.build.version.release
查看Android SDK版本
adb shell getprop ro.build.version.sdk
强制终止当前运行的应用
adb shell am force-stop 包名
push文件到lib
adb push 文件路径 /data/data/包名/lib
命令启动MainActivity
adb shell am start 包名/.MainActivity
目前正在学习《自然语言处理入门》这本书,第二章 词典分词部分涉及字典树的内容较多,在字典树的基础上又介绍了首字散列其余二分的字典树、双数组字典树、AC自动机,越往后难度越大越难理解,因此理解字典树非常重要,所以参考原书代码和网上代码,敲了一遍首字散列其余二分的字典树的python实现代码,目的在于加深对字典树的理解。
算法和概念部分可学习参考资料2,此处不再赘述。
首字散列其余二分的字典树结构示意图:
# Author: 勤奋的清风 # Date: 2022-05-18 # BinTrie.py def char_hash(char, length=5): # 由于python没有字符类型,而字符串hash code长度为64位,将其截取五位 return abs(hash(char)) % (10 ** length) class Node(object): def __init__(self, key, value=None): self._children = [] # 子节点为数组 self._key = key # 节点代表的值 self._value = value # 节点值 def __getitem__(self, key): if not self._children: return None idx = self.binary_search(self._children, key) if idx < 0: return None return self._children[idx] def compareTo(self, other): """比较字符hash值大小""" if type(other) !
VMware虚拟机扩展磁盘容量 环境:VMware 15.5.0 + Ubuntu16.04
扩容之前:
目标:将原来的50G扩展为150G
1. 关闭虚拟机,设置扩展磁盘容量
步骤如下图所示
确认后就可以开启虚拟机了!
注: 虚拟机关机后修改硬盘容量才有效,另外如果有快照的话也要先删除快照才能设置扩展磁盘容量
通过快照管理器删除
2. 打开虚拟机,分配扩展出来的磁盘容量
2.1 使用gparted工具,删除原来的扩展分区和逻辑分区
2.1.1 安装gparted
如果虚拟机Ubuntu没有安装gparted工具的话,需要先安装该工具
sudo apt-get install gparted 我这里已经安装过了,所以可直接搜索打开gparted
打开GParted后,可以看到有100G的磁盘空间处于未分配状态
那么接下来就需要将这100G分配到主分区/dev/sda1中,主分区和未分配区之间不能有其他分区,所以要先将他们之间的分区去掉,步骤如下:
2.1.2 删除逻辑分区
选中/dev/sda5所在区域,单击右键,禁用交换空间(Swapoff)
再次选中/dev/sda5所在区域,单击右键,此时点击Delete删除该分区
PS:需要先禁用交换空间,才能删除该分区
2.1.3 删除扩展分区
选中/dev/sda2所在区域,单击右键,点击Delete删除扩展分区
删除后,只剩下主分区和未分配区
磁盘容量与主分区、扩展分区、逻辑分区的关系: 硬盘容量 = 主分区容量 + 扩展分区容量 扩展分区容量 = 各个逻辑分区容量之和 2.2 修改主分区大小,重新创建扩展分区和逻辑分区
2.2.1 修改主分区大小
进入主分区大小调整界面,将之后的剩余空间(Free space following)修改为1024,即预留1G空间用来创建刚刚被删除了的逻辑分区和扩展分区;随后点击Resize重新分配大小
2.2.2 创建扩展分区
选中未分配区域,单击右键,点击New
选中创建为扩展分区(此时File system会自动识别为extended)
点击Add,完成创建
2.2.3 创建逻辑分区
选中未分配区域,单击右键,点击New,创建逻辑分区,文件系统File system下拉选择为linux-swap
点击Add,完成创建
2.2.4 应用上述操作
完成逻辑分区和扩展分区的创建后,此时点击应用(绿色√)
等待完成操作,然后点击close
关闭后即可看到如下界面,扩展分区和逻辑分区创建完成,名称自动识别为/dev/sda2和/dev/sda5,主分区大小更新为149G
目录
官方文档:
一、简介:
高性能
分区的设计
顺序读写
零拷贝技术
减少网络传输上的开销
基础组件:
kafka节点:broker
主题:topic
分区:partition
副本:Replication
同步副本集合ISR(in-sync replicas)
概念:
特点:
非同步状态副本OSR(Outof-sync Replicas)
partition中leader replication的选举:
Kafka 为何不采用大多数投票机制(quorum算法)来选举leader 。
Unclean 领导者选举(Unclean Leader Election)
follower同步leader的数据:
同步方式:
优点:
常见配置:
producer
数据发送方式:
consumer
接收数据方式:
拉模式的优点:
推模式(push-based)消费的缺点:
consumer group
配置
Producer配置
acks:
batch.size
Broker配置
优化
producer如何优化打入速度
consumer如何优化消费速度
Kafka中的ZooKeeper
管理 Broker 、Consumer Group、Consumer、Producer
思考
为什么Kafka不支持读写分离?
官方文档: Apache KafkaKafka 中文文档 - ApacheCN重点关注 4. 设计思想 一、简介: 以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 TB 级以上数据也能保证常数时间复杂度的访问性能。 高性能 分区的设计 负载均衡:
JSON 1、JSON概述 JSON:JavaScript Object Notation(JavaScript 对象标记法),它是一种存储和交换数据的语法。
当数据在浏览器与服务器之间进行交换时,这些数据只能是文本,JSON 属于文本并且我们能够把任何 JavaScript 对象转换为 JSON,然后将 JSON 发送到服务器。我们也能把从服务器接收到的任何 JSON 转换为 JavaScript 对象。以这样的方式,我们能够把数据作为 JavaScript 对象来处理,无需复杂的解析和转译。
2、JSON语法 在json中,每一个数据项,都是由一个键值对(或者说是名值对)组成的,但是键必须是字符串,且由双引号包围,而值必须是以下数据类型之一:
字符串(在 JSON 中,字符串值必须由双引号编写)数字对象(JSON 对象)数组布尔null JSON 的值不可以是以下数据类型之一:
函数日期undefined 因为 JSON 语法由 JavaScript 对象标记法衍生而来,所以很少需要其它额外的软件来处理 JavaScript 中的 JSON。
通过 JavaScript,您能够创建对象并向其分配数据,就像这样:
var person = {"name": "zhangsan", "age": 62, "city": "BeiJing"}; console.log(person); 3、JSON数据类型 3.1、JSON 字符串 JSON 中的字符串必须用双引号包围。
{"name": "John"} 1
3.2、JSON 数字 JSON 中的数字必须是整数或浮点数。
{"age": 30} 3.3、JSON 对象 JSON 中的值可以是对象,JSON 中作为值的对象必须遵守与 JSON 对象相同的规则。
1.removeAbandoned removeAbandoned功能常用来进行连接泄露检查,该功能共有三个参数进行组合配置。
参数类型默认值含义removeAbandonedBooleanfalse是否开启removeAbandoned功能removeAbandonedTimeoutLong300000活动时间超过该参数值的连接将被自动回收logAbandonedBooleanfalse是否开启日志打印回收信息 2.removeAbandoned功能如何实现自动回收长链接 removeAbandoned功能是由DruidDataSource#removeAbandoned方法进行处理,该方法将对存储于activeConnections中的连接进行遍历,通过对DruidPooledConnection中的相关状态进行跟踪来判断是否满足回收条件。
public int removeAbandoned() { //驱逐计数 int removeCount = 0; //得到当前时间 long currrentNanos = System.nanoTime(); //创建List,用于记录需要被驱逐的连接 List<DruidPooledConnection> abandonedList = new ArrayList<DruidPooledConnection>(); //加锁,避免出现线程问题 activeConnectionLock.lock(); try { //以迭代器的形式获得activeConnections的所有Key(即连接对象) Iterator<DruidPooledConnection> iter = activeConnections.keySet().iterator(); //遍历迭代器 for (; iter.hasNext();) { //获得当前连接 DruidPooledConnection pooledConnection = iter.next(); //如果当前连接正在执行中,则暂不处理 if (pooledConnection.isRunning()) { continue; } //判断该连接存在时间,取值为当前时间-创建连接时间/1000*1000(将纳秒转为毫秒) long timeMillis = (currrentNanos - pooledConnection.getConnectedTimeNano()) / (1000 * 1000); //如果连接存在时间超过了指定值 if (timeMillis >= removeAbandonedTimeoutMillis) { //移除该连接 iter.remove(); //取消对该连接的跟踪 pooledConnection.
1.首先把crx文件修改名字,改成.zip结尾的文件 2.把需要的zip解压 3.chrome浏览器打开开发者模式 4.加载已解压的扩展程序 5.先添加tampermonkey,再添加simple-allow-copy 6.把扩展程序固定到浏览器工具栏 7.在bd文库中,先点亮扩展程序(点一下图标,可能有些页面点亮不了) 如果是文字的话,可以复制文字;
如果是图片的话,可以右键,另存为
一、定义 :mysql官方定义:索引时帮助mysql高效的获取数据的数据结构。可以得到索引的本质:数据结构
是一种排好序的快速查找的数据结构 ( 查找+排序 两大功能)
也就是说:索引会影响到查找where后面的过滤,和 order by 中的排序
之所以查的快,是因为给你排好序了。
创建索引后,只对创建了索引的列有效。
执行流程:在任何数据库当中,任何一张表的任何一条记录在硬盘存储上都会有一个硬盘的物理存储编号。通过索引拿到物理存储编号,定位记录。
二、索引的优劣势 优势:
1.缩小扫描范围,拿到物理存储编号,定位这条记录,避免全表扫描。
2.提高了数据检索的效率,降低数据库的I/O成本。
3.通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗。
索引的代价
1.索引本身也会占用磁盘空间
2.索引虽然大大提高了查询速度,但是对dml(update delete insert)语句的效率有影响, mysql不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段。比如说 delete 时,会导致二叉树会重新构造。
3.另外索引的建立也是需要花时间研究建立性能好的索引,不断的重建测试进行优化
三、索引的拓展知识 1.当没有创建索引时,会进行全表扫描,依次比较。索引在mysql中,是一个单独的对象
创建索引,会形成二叉排序树,B树、B+树都有可能有。不同的存储引擎以不同的形式存在,再myisal存储引擎中,索引存储在一个 .myi文件中 。在innodb存储引擎中,索引存储在一个逻辑名称叫做tablespace文件当中。在memory存储引擎当中索引被存储在内存当中。不管索引存储在哪里,索引在mysql当中都是一个树的形式存在 (自平衡二叉树:B-Tree)
2.索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。我们常说的索引,如果没有特别指明,都是B树(多路搜索树,并不一定是二叉的)结构组织的索引。其中聚集索引,次要索引,复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种类型的索引之外,还有哈希索引等。
四、索引的类型 1.主键索引,主键自动的为主索引 (类型 primary key) ,主键也是一种唯一索引?
2.唯一索引 (unique)约束也会自动创建索引对象
3.普通索引 (index)
4.全文索引 (fulltext)【使用于mylsam】
mysql自带的全文索引不好用,在开发中考虑使用:全文搜索 solr 和 elasticsearch (ES)
单值索引:即一个索引只包含单个列,一个表可以有多个单列索引。
唯一索引:索引列的值必须唯一,单允许有null值。 复合索引:
总结:复合索引一定优于单值索引 。 (一张表最好只建5个左右的索引)
mysql索引结构:Btree索引、Hash索引、full-text全文索引、R-Tree索引
另外,一个列只能添加一个索引
五、索引的基本语法 1.查询索引
show index/indexs/keys from 表名
2.创建索引:
方式1:create 【unique / fulltext】 index 索引名 on 表名(列名 / 复合索引); 方式2:alter table 表名 add 【unique / fulltext】 index 索引名 on (列名 / 复合索引);
MySQL高级进阶 (1)MySQL的开窗函数 ROW_NUMBER:从 1 开始,按照顺序生成组内的记录编号;RANK:从 1 开始,按照顺序,相同会重复,名次会留下空的位置,生成组内的记录编号;DENSE_RANK:从 1 开始,按照顺序生成组内的记录编号,相同会重复,名次不会留下空的位置; (2)语法结构 函数 over (partition by XXX order by XXX)over():以谁进行开窗【table】partition by: 以谁进行分组【group by column】order by: 以谁进行排序【column】 开窗函数区别如下图所示:
(3)内置窗口函数 FIRST_VALUE:取窗口第一个值LAST_VALUE:取窗口最后一个值 ==注意:== 这里也是一个动态的当第n行时,如果不做特殊指定,当到达第n行时,每组的窗口范围是 从第1行到第n行,因此第一组的窗口的FIRST_VALUE都是第1行的值,LAST_VALUE都是当前行的值 MySQL中的三种条件判断函数 (1)IF() IF ( EXPR , V1 , V2 )
执行逻辑:若 expr 为 ture 则 V1 否则 V2
(2)IFNULL() IFNULL(字段,0)
执行逻辑:如果字段为 null 的话,就用 0 进行填充
(3)CASE WHER :类似于java中的if...else...函数 -- 如果字段值等于预期值,则返回结果 1 ,否则返回结果2
CASE 字段 WHEN 预期值 THEN 1 ELSE 2 END
要简单实现轮播图,就需要用到js中的定时器。通过定时器来设定时间,从而达到轮换播放的效果。
具体代码如下:
var n=1; function lb(){ n++; if(n>3) { n=1; } var img = document.getElementById("lunbo"); img.src="img"+n+".png"; } setInterval(lb,3000); 其中n代表循环中的个数,通过利用n的变换来更改所获得的img中的src属性,从而达到轮播的效果。
输入一组整,将这组数组从大到小逆序排列,并按照指定格式输出。
输入格式: 一行一组数据
输出格式: 指定的格式输出逆序
输入样例: 1 2 3 4 5 6 7 8 输出样例: 8->7->6->5->4->3->2->1 ss = [] ss = input().split() a = 0 ss.sort() #将字符串进行排序(从小到大) ss.reverse() #字符串逆序 for i in range(len(ss)): a+=1 if a<len(ss): #为了让末尾没有箭头 print(ss[i],end='->') else: print(ss[i])
编写一个凯撒密码加密程序,接收用户输入的文本和密钥k,对明文中的字母a-z和字母A-Z替换为其后第k个字母。
输入格式: 接收两行输入,第一行为待加密的明文,第二行为密钥k。
输出格式: 输出加密后的密文。
样例">输入样例: 在这里给出一组输入。例如:
Hello World! 3 输出样例: 在这里给出相应的输出。例如:
Khoor Zruog! isalpha():isalpha函数用来检测字符串是否由字母组成
a = input() b = int(input()) c = '' for i in a: if i.isalpha(): #这里的isalpha用来判断i是否为字母 temp = ord(i)+b if chr(temp).isalpha(): #加密之后还是字母 c += chr(temp) else: #加密之后不是字母 c += chr(temp-26) else: c += i print(c)
实现一个加密函数easyCrypto(),带两个输入参数:一个需加密的字符串,一个3位数字字符串的秘钥,输出密文。
加密规则:对于出现的第一个字母,按第一个数字后的字母变换,出现的第二个字母按第二个数字,出现的第三个字母按第三个数字,出现的第四个字母按第一个数字,以此类推,字母之外的字符保持不变。
输入格式: 第一行输入要加密的字符串
第二行输入3位数字字符串
输出格式: 输出加密后的字符串
输入样例1: 在这里给出一组输入。例如:
abcde 123 输出样例1: 在这里给出相应的输出。例如:
bdfeg 输入样例2: 在这里给出一组输入。例如:
aA,zZ 111 输出样例2: 在这里给出相应的输出。例如:
bB,aA ord():ord函数可以返回一个字符的ASCII数值
aa = list(input()) bb = list(map(int,input())) cc = -1 for i in range(0,len(aa)): if 65<=ord(aa[i])<=90: #判断是否为大写 cc +=1 aa[i] = chr((ord(aa[i])-65+bb[(cc%3)])%26+65) if 97<=ord(aa[i])<=122: #判断是否为小写 cc +=1 aa[i] = chr((ord(aa[i])-97+bb[(cc%3)])%26+97) print(''.join(map(str,aa)))
问题场景 场景很简单,就是一个正常 axios post 请求:
axios({ headers: { 'deviceCode': 'A95ZEF1-47B5-AC90BF3' }, method: 'post', url: '/api/lockServer/search', data: { username, pwd } }) 后台说没有接收到你的传参。
这就有点奇怪了,我看了一下浏览器的请求信息是 OK 的,参数都是有的,而且之前这样用 axios 也没有这个问题。
但是这个接口是通用的,别人都用了,是 OK 的,接口没问题。
问题原因 要点1 原因就是这次的接口使用 java spring mvc 并且在这个方法上使用了注解 @RequestParam
那么这个是什么意思呢,这个是只能从请求的地址中取出参数,也就是只能从 username=admin&password=admin这种字符串中解析出参数。
要点2 我们还可以看到我们这次请求的 Content-Type:
application/json;charset=UTF-8 关于这一点需要说明的是:
1、axios会帮我们 转换请求数据和响应数据 以及 自动转换 JSON 数据 2、在 axios 源码中发现下面这段内容:(很关键) 我们知道在做 post 请求的时候,我们的传参是 data: {...} 或者直接 {...} 的形式传递的,嗯,就是下面这两种形式
【第一种形式】 【第二种形式】 非常的刺激,这两种形式无一例外都触发了 axios 源码中【很关键】的那一段代码
问题分析 也就是说,我们的 Content-Type 变成了 application/json;charset=utf-8 然后,因为我们的参数是 JSON 对象,axios 帮我们做了一个 stringify 的处理。 而且查阅 axios 文档可以知道:axios 使用 post 发送数据时,默认是直接把 json 放到请求体中提交到后端的。
一、UBI文件系统的概述
UBIFS是由诺基亚工程师在塞格德大学的帮助下开发的一种新的闪存文件系统。在某种程度上,UBIFS可以被认为是JFFS2文件系统的下一代。
UBI 意思是"Unsorted Block Images未排序的块镜像"。UBIFS是一个flash文件系统。UBIFS与Linux中的传统文件系统如Ext2,XFS,JFS等完全不同。UBIFS 表示一类单独的文件系统,它们与 MTD 设备(而不是块设备)一起使用。此类的另一个 Linux 文件系统是 JFFS2。
JFFS2 文件系统与UBIFS文件系统的区别在于:JFFS2在 MTD 设备之上工作,但 UBIFS 在 UBI 卷之上工作,不能在 MTD 设备上运行
二、UBIFS涉及三个子系统
解释
MTD子系统
MTD子系统用于屏蔽不同flash的操作差异,向上提供统一的操作接口,对应kernel的代码位于drivers/mtd。MTD在flash驱动之上,向上呈现统一的操作接口
UBI子系统
UBI子系统基于MTD子系统之上,在MTD上实现nand特性的管理逻辑,向上屏蔽nand的特性;对应drivers/mtd/ubi
UBIFS文件系统
基于UBI子系统的文件系统,实现文件系统的所有基本功能。例如文件的实现,日志的实现等;对应kernel的代码位于fs/ubifs
三、UBIFS的功能列表
1、可扩展项。UBIFS相对于闪存大小具有良好的可扩展性。挂载时间,内存消耗和I / O速度不取决于闪存大小。UBIFS应该可以在数百GiB的flash上正常工作。UBI / UBIFS堆栈的扩展性比JFFS2好得多
2、快速安装。UBIFS几毫秒就能安装,安装不取决于闪存大小,但UBI初始化时间与闪存大小相关
3、写回支持。JFFS2是直写,UBIFS提高了许多工作负载中文件系统的吞吐量
4、容忍不干净的重启。UBIFS是一个日志文件系统,它容忍突然崩溃和不干净的重新启动。在遇到不干净的重启时,挂载时间稍慢,因为需要重放日志,但 UBIFS 不需要扫描整个介质,因此挂载 UBIFS 无论如何都需要几分之一秒的时间
5、快速I/O。在同步I/O中与JFFS2竞争是极其困难的,因为JFFS2不在闪存上维护索引数据结构,因此它没有维护开销,而UBIFS需要。但是UBIFS仍然很快,因为UBIFS提交日志的方式——不会将数据从一个地方物理移动到另一个地方,而是将相应的信息添加到文件系统索引中,并为新日志选择不同的擦除块,还有其他技巧,如多头日记,这些特性使得UBIFS I/O速度表现良好
6、动态压缩。数据以压缩形式存储在闪存介质上,这与JFFS2非常相似。UBIFS还允许在每个inode的基础上打开/关闭压缩,这非常灵活。
7、可恢复性。如果索引信息损坏,UBIFS 可能会被完全恢复。UBIFS中的每条信息都有一个描述该信息段的标头,并且可以通过扫描闪存介质完全重建文件系统索引,这与JFFS2非常相似。
8、完整性。UBIFS(以及UBI)会校验写入闪存的所有内容以保证数据完整性,UBIFS不会让数据或元数据损坏被忽视(同JFFS2)。默认情况下,UBIFS在从flash读取时仅检查元数据CRC,而不检查数据CRC,但是也可以使用其中一个 UBIFS 挂载选项强制 CRC 检查数据
四、UBI文件系统的制作
制作UBI文件系统时常用的命令有: 工具
作用
ubinfo
提供ubi设备和卷的信息
ubiattach
链接MTD设备到UBI并且创建相应的UBI设备
ubidetach
ubiattach相反的操作,将MTD设备从UBI设备上去链接
ubimkvol
从UBI设备上创建UBI卷
ubirmvol
从UBI设备上删除UBI卷
ubiblock
管理UBI卷上的block
问题描述:
以4皇后为例,其他的N皇后问题以此类推。所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子。在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平、竖直、以及45度斜线上都不能出现皇后的棋子。
回溯法:dfs+迭代
1.如何判断当前位置的取值满足条件:
假设一个变量,每次设值都与前面已经设置好了的皇后的位置进行比较,是否同行同列,同斜线可以使用表达式:a[i]=a[j]=i-j || a[i]-a[j]=j-i
2.什么情况下成功找到四皇后的摆放位置:
当i>4,也就是当前设值的位置已经是最后一个皇后了并且设置的位置也能满足条件
3.什么情况下四个皇后还没有全部确定完,还需要进行查找下一个:
当i=1并且i<4时,这时候还有皇后没有确定位置,还需要进行查找
4.什么情况下进行回溯:
当i=0时并且a[i]=4并且i>1时,ok=0表示当前位置的值不能满足,a[i]=4表示当前位置所有的值都设置过了仍然没有满足条件的,i>1表示还可以进行回溯,如果i=1时表示它是第一个皇后,就没有进行回溯的对象了,那程序就可以终止了
5.什么情况下探索完毕,程序终止:
当a[i]=4并且i=1时,已经没有回溯的对象了,这时候程序就终止了
#include<iostream> #define N 4 using namespace std; void Print(int n, int a[]) { for (int j = 1; j <= n; j++) cout << a[j] << " "; //输出最终的棋盘布局,每个数组元素值表示各行棋盘所在的该列放置皇后 cout << endl; } int isOk(int i, int a[]) { //检查当前棋盘布局是否合理 for (int j = i - 1; j>= 1; j--) if (a[i] == a[j] || abs(a[i] - a[j]) == i - j) return 0; return 1; } void queen(int i, int n, int a[]) { //进入本函数前,前i-1行已经放置了互不攻击的i-1个皇后 if (i > n) Print(n, a); //如果i已经大于最大的行数了,那么说明布局完成,则打印结果 else { for (int j = 1; j <= n; j++) { a[i] = j; //在第i行第j列放置一个皇后 if (isOk(i, a)) queen(i + 1, n, a); //当前布局合理,进行下一行的布局 a[i] = 0; //移走第i行第j列放置的皇后, 回溯。 } } } int main() { int ct[N] = { 0 }; //棋盘的初始状态,棋盘上无任何皇后 queen(1, N, ct); //摆放皇后 return 0; } 分支限界法:剪枝
配置 打开OpenFeign对Sentinel的支持
spring: application: name: order-service cloud: nacos: # nacos服务地址 server-addr: 192.168.31.233:8847 # 连接账号/密码 默认账户密码 nacos/nacos discovery: username: nacos password: nacos feign: # 打开OpenFeign对Sentinel的支持 sentinel: enabled: true 启用类上开启Feign支持
@SpringBootApplication @EnableFeignClients //开启Feign支持 public class OrderOpenfeignApplication { public static void main(String[] args) { SpringApplication.run(OrderOpenfeignApplication.class, args); } } 实现 使用注解@FeignClient 标记服务提供者的接口,FeignClient 的fallback 属性可以指定控流和异常处理。
/** * 服务提供者 * @FeignClient * value:服务提供者服务名称 * path:调用路径 * fallback:流控异常处理 */ @FeignClient(value = "stock-service",path = "/stock",fallback = StockFeignSeriveFallback.class) public interface StockFeignService { @RequestMapping("
来源:https://zhengyu.tech
无法对tf的内容进行录制 问题描述: 当我们利用rosbag record对/tf进行录制时,有时候会发现有些节点并没有被录制,而这些节点确实存在。比如我们利用robot_state_publisher发布机器人的关节tf信息,就会出现该问题。
进一步仔细观察导出的tf树图,我们可以发现问题:没有被录制的节点并没实时在发布tf信息,所以才导致了该问题。
解决方法: 这是由于ros添加了tf_static机制,使得对相对固定的tf不必重复发布,从而占用宝贵的带宽。我们只需在关闭该功能即可:
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" args="robot_description:=robot_description" <param name="use_tf_static" value="false" /> </node> 无法对tf进行重映射 问题描述: 当我们在利用rosbag时,有时候希望对tf名进行重映射,来适配当前代码。例如,H_imu_link_record—> H_imu_link,我们可以很快找到对应功能模块remapper来实现,但是依旧没有变换。
<node name="remapper" pkg="tf" type="tf_remap" output="screen"> <rosparam param="mappings">[{old: H_imu_link_record, new: /H_imu_link}, ]</rosparam> </node> 解决方法: 其实,我们还需要对原/tf也进行重映射,才能够实现:
<node pkg="rosbag" type="play" name="player" args="/home/sbdx/Documents/2022_03_04_16_33_48.bag" output="screen"> <remap from="tf" to="tf_old" /> </node>
问题 Intel12代CPU装了ubuntu20后核显无法识别屏幕,以及无法扩展屏幕
解决 # 打开grub文件 sudo vim /etc/default/grub # 将对应参数修改 GRUB_CMDLINE_LINUX_DEFAULT="quiet splash i915.force_probe=4680" # 更行grub sudo update-grub # 重启 reboot 来源:https://zhengyu.tech
link
一、 目的 根据上课讲的吴迪老师的微信好友数据分析,请选择你的微信好友数据,或者你的qq好友数据,或者你的班级同学数据,或者其他你能获取的其他人物数据
作为分析对象。然后利用上课讲的技术,但不限于,对其进行数据分析。比如分析微信好友数据,可以可视化好友男女比例分布,可视化省份来源,可视化签名的情感强度值等等。
要求:1分析数据用xls或者csv格式存储。
2.代码用py文件附件形式上传,方便我的下载。
3.在作业里可以介绍你的主要功能和可视化截图。
4.根据功能完整性和结果的酷给分。
二、项目完成功能总结 1:饼状图统计好友男女比例
2:柱状图学生省份和城市分析
3:分析191,192学生情感
4:柱状图17·18·19级学生男女比例
5:关系图example
6:词云
7:好友省份地图可视化
8:好友城市地图分析
9:好友头像集成大图
10: 微信好友名称分析职业特点
三、前期准备 1、需要用到的库 import os
import math
from PIL import Image
from pyecharts.charts import Pie
from pyecharts.charts import Bar
from pyecharts.charts import WordCloud
#用于设值全局配置和系列配置
from pyecharts import options as opts
import csv
import xlrd
import re
import jieba
from snownlp import SnowNLP
import matplotlib.pyplot as plt
import numpy as np
文章目录 作者简介引言导航热门专栏推荐概述安装JRebel注册JRebel配置JRebel最后小结导航热门专栏推荐 作者简介 作者名:编程界明世隐
简介:CSDN博客专家,从事软件开发多年,精通Java、JavaScript,博主也是从零开始一步步把学习成长、深知学习和积累的重要性,喜欢跟广大ADC一起打野升级,欢迎您关注,期待与您一起学习、成长、起飞!
引言 我本来是一直用eclipse和myeclipse的老程序员了,很多我的粉丝小伙伴都说他们要用idea,问我怎么不用idea,其实明哥觉得用啥开发工具都不是重点,重点是要跟着明哥多学Java知识、多练习,但是作为一个宠粉的人,我怎么能拒绝粉丝的要求呢,于是我偷偷的去学习了一波(拿来吧你),然后就写了这个系列,希望小伙伴们能有所收获,明哥会努力更新的。
概述 作为web程序员,热部署对我们来说嘴熟悉不过了,如果项目没有热部署的话,会相当的麻烦,改了代码就得重新启动,如果项目比较大的话,启动要花很久的时间,有款叫Jrebel的插件非常好用,能够大大的提高工作效率,下面就来介绍怎么安装和使用这个插件。
安装JRebel 方式1:直接在插件市场安装,简单,但是我反正搜索不出来,好像要翻墙。
方式2:就是从网上去下好插件包,然后从本地安装了,就采用这个了。
下载方式
从网盘下载:公众号,编程界明世隐,回复:jrebel
打开网址下载:https://plugins.jetbrains.com/idea网址下载,输入jrebel查询,并选择第一个:
选择自己想要的版本下载 打开settings,选择插件项,选择从本地安装,如下图: 选择下载好的插件(注意下载下来是zip,不要解压哦)需要重启IDEA才会生效 点击重新启动 注册JRebel 点击如下图,进入注册页面 注册页面如下: 注册需要GUID 网站:https://www.guidgen.com
获取一个新的GUID
将新的GUID和jrebel的网站合并在一起(GUID放到后面),如: https://jrebel.qekang.com/GUID 把这里的GUID换成新生成的
邮箱随便填,符合邮箱规则就行
注册成功 配置JRebel 确保IDEA的自动编译功能是打开的
打开settings–Build,Execution…–Compiler
左下方jrebel处勾选当前项目 使用JRebel的debug模式启动项目 启动完成打开项目测试地址(地址看你自己项目的)
启动的时候会有JRebel的相关信息,然后是项目的日志信息 我这里的地址是:http://localhost:8080/hello
修改代码内容,并手动构建项目(快捷键 ctrl+F9) 代码生效,页面效果 调整自动热部署的时间,在settings里面
这是可以不手工构建,自动间隔一定时间会构建一次项目,看自己的需要去调整。
最后 在这里我不得不说的是,我无意中用debug模式,在没有用JRebel 的debug模式情况下,直接按了 ctrl+F9 竟然也自动热部署了,这个就很尴尬,也就是说前面的都白瞎了?我晕倒。。。,给我个痛快吧。
我只能说一句:IDEA威武,YYDS!
小结 这节总结了“ IDEA中安装并使用JRebel热部署插件”,希望能对大家有所帮助,请各位小伙伴帮忙 【点赞】+【收藏】+ 【评论区打卡】, 如果有兴趣跟小明哥一起学习Java的,【关注一波】不迷路哦。
---------------------
作者:编程界明世隐
来源:CSDN
原文:https://blog.csdn.net/dkm123456/article/details/121884604
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件
Druid在什么时候会创建连接 CreateConnectionTask#runInternal
CreateConnectionTask是用于Druid中用于创建连接的任务,实现了Runnable接口,主要用于向线程池中提交任务。
public class CreateConnectionTask implements Runnable { private int errorCount = 0; private boolean initTask = false; private final long taskId; public CreateConnectionTask() { taskId = createTaskIdSeedUpdater.getAndIncrement(DruidDataSource.this); } public CreateConnectionTask(boolean initTask) { taskId = createTaskIdSeedUpdater.getAndIncrement(DruidDataSource.this); this.initTask = initTask; } @Override public void run() { runInternal(); } private void runInternal() { //创建循环,保证可以获取到连接 for (;;) { // addLast //加锁创建 lock.lock(); try { //如果当前连接池被关闭或者处于关闭状态 if (closed || closing) { //清除创建任务,停止执行 clearCreateTask(taskId); return; } //空等待状态 boolean emptyWait = true; //如果出现创建异常并且连接池中没有连接,空等待状态设为false if (createError !
我们在之前分析源码的时候 ,说到了连接池初始化的中非常关键的两个方法 ,分别是 createAndStartCreatorThread() 和 createAndStartDestroyThread(),他们分别代表了连接的创建和销毁逻辑,我们上次从整个流程提炼出来,并对销毁逻辑做了拆解,这次我们再补齐对连接的创建逻辑的内容:
创建连接任务的主要流程如下: [ 创建链接的核心流程 ]
0.入口 protected void createAndStartCreatorThread() { if (createScheduler == null) { String threadName = "Druid-ConnectionPool-Create-" + System.identityHashCode(this); createConnectionThread = new CreateConnectionThread(threadName); createConnectionThread.start(); return; } initedLatch.countDown(); } 1.核心创建流程 public void run() { initedLatch.countDown(); long lastDiscardCount = 0; int errorCount = 0; for (;;) { // addLast try { // 获取锁 lock.lockInterruptibly(); } catch (InterruptedException e2) { break; } long discardCount = DruidDataSource.