STM32CubeMX:配置硬件CRC 对比软件CRC计算

关键词: CRC,STM32硬件CRC 调试环境:Keil 编译器:Keil 驱动生成:STM32CubeMX 开发板:STM32F334C8T6 核心开发板 测试目的: 1:记录硬件CRC的使用方法; 2:对比硬件、软件 CRC16 的计算耗时; 一、STM32硬件CRC功能配置 1.1按如下选项配置: 注意:以下配置是为了硬件计算结果与软件计算模式相同。实际硬件配置方式多样,这里仅取如下方式作为对比。 配置参数放大截图 1.2生成代码,并找到 crc.c ,crc.h 文件,里面有crc的初始化代码 代码如下: #include "crc.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ CRC_HandleTypeDef hcrc; /* CRC init function */ void MX_CRC_Init(void) { /* USER CODE BEGIN CRC_Init 0 */ /* USER CODE END CRC_Init 0 */ /* USER CODE BEGIN CRC_Init 1 */ /* USER CODE END CRC_Init 1 */ hcrc.

深度学习/语义分割入门笔记(一)——遥感影像数据集及标签制作+arcgis批量矢量转栅格

目录 一、目的 二、深度学习?语义分割? 三、遥感数据集及标签的制作 数据集制作步骤: 批量矢量转栅格步骤: 四、参考视频/文章: 一、目的 对遥感影像进行语义分割。初学看了很多教程,网上这方面内容较多同时也十分杂乱,选择价值高的信息也成为了一个费时费力的难点,总结了一下最近几天看的各种内容,做个笔记。 二、深度学习?语义分割? 深度学习的课程可谓是十分之多,很多都是关注公众号或者加微信来卖课,大家自己斟酌。这里推荐b站白嫖。基础背景不再多说,这里主要记录我遇到的问题。 目前深度学习的主要三个方向分别是图像分类、目标检测和语义分割: 其中图像分类主要针对图片,比如识别一张动物的照片是猫是狗;目标检测的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,进行定位和生成标记物体的边界框;语义分割主要针对像素点进行分类,把每一个像素点都标注上其对应的类别。 根据自己的研究目的来选择相应的方法手段,这里我的需求是针对像素点的语义分割。 三、遥感数据集及标签的制作 【最新笔记在​​​​​​​【实验笔记】谷歌地图配准哨兵二号影像制作遥感影像数据集-CSDN博客】 看了很多教程,目前深度学习数据集的制作主要分为手动和半自动两类。对于一般的不含地理信息的图片(RGB三通道图像或者灰色单通道图像)可以采用半自动的方法进行制作,主流软件有label me、anylabeling等。对于图像的格式介绍在这里关于数据集处理的若干格式-CSDN博客 在遥感图像中,不同于普通图片,通常是包含更多信息比如地理信息以及多个光谱波段的栅格数据,后缀一般为tif,多光谱的遥感影像对于地物识别具有重要意义,自然不能舍弃。我参考了b站一个up的arcgis pro + anylabeling半自动制作遥感影像数据集,最后发现软件并不支持我的四通道16位的tif数据(也可能是我没弄明白),最终选择了手动划分的方法。 数据集制作步骤: 1、使用arcgis pro打开遥感影像。 2、生成随机点。点击【视图】-【地理处理】-【创建随机点】,按照需求填写输出信息。 3、建立缓冲区。【地理处理】-【缓冲区】,同上根据需求填入信息。 4、输出数据集。【地理处理】-【导出训练数据进行深度学习】。 5、数据集标签制作。在arcmap中打开tif,对其进行标注。这里以其中一个为例进行说明。 导入tif影像;新建shp面要素,导入选择与tif源文件相同的坐标系。 右击shp打开属性表,添加字段class_id; 开始编辑,将需要分类的要素进行框选,框选后在属性表中对class_id字段进行赋值。 需要说明的是,这里分为二分类和多分类。也就是可以手动将不同类型的部分都划分出来,分类赋不同的值,也可以使用二分类,将需要提取的内容赋值为1,其他部分全部赋值为0。这里我使用二分类。标注完成。 6、批量面转栅格。上述标注的标签为shp格式,还需要将shp面要素转为tif格式来使用。单个转的话,arcgis工具箱【转换工具】-【转为栅格】-【面转栅格】设置好与原tif相同的像元大小,以及上述标注的“class_id”字段即可。但由于数据集一般过大,这里建议使用批量的方法来处理。 批量矢量转栅格步骤: 使用工具:arcgis安装自带的python2.7+集成开发环境pycharm2022.3软件下载:arcgis不必多说,pycharm的话,建议不要使用最新版,第一新版本某些功能不太稳定,第二2023.2不支持中文汉化包。官网下载地址:其他版本 - PyCharm (jetbrains.com)软件激活:PyCharm 2022.3 激活破解码_安装教程 (持续更新~) - 异常教程 (exception.site)环境配置:打开pycharm,选择【文件】-【新建项目】-【添加解释器】-【添加本地解释器】 ​ 注意这里选择【系统解释器】,不要选第一个【虚拟环境】,会发生不幸! ​ 代码编写:(这里我的字段用的是id) # coding=utf-8 import os import arcpy from arcpy import env # 设置工作空间为包含 shp 文件的目录 env.workspace = r"D:\DayDayUP\Eco_data\DeepData\shp" # 设置保存转化后的影像路径 save_path = r"

arm-eabi-gcc 和 arm-none-eabi-gcc 都是基于 GCC 的交叉编译器

arm-eabi-gcc 和 arm-none-eabi-gcc 都是基于 GCC 的交叉编译器,用于编译 ARM 架构的嵌入式系统。它们的命名规则如下: arm 表示目标架构是 ARM。eabi 表示嵌入式应用程序二进制接口(Embedded Application Binary Interface),是一种用于嵌入式系统的标准接口。gcc 表示 GNU 编译器集合(GNU Compiler Collection),是一种开源的编译器。none 表示没有指定供应商或操作系统。 它们的主要区别是: arm-eabi-gcc 是 Android 平台使用的交叉编译器,它可以编译 Android 的 boot、kernel、filesystem 和应用程序等。它使用的是 Bionic C 库,这是一种专门为 Android 设计的轻量级 C 库。1arm-none-eabi-gcc 是 ARM 官方提供的交叉编译器,它可以编译 ARM 的裸机系统,不适用于编译 Linux 应用程序。它使用的是 Newlib C 库,这是一种专门为嵌入式系统设计的小型 C 库。2 我在网上搜索了一些可能的来源和下载链接,您可以参考以下信息: Android NDK | Android Developers:这是 Android NDK 的官方网站,Android NDK 是一个用于在 Android 应用中集成 C 和 C++ 代码的工具集。Android NDK 提供了一系列的工具,包括 arm-eabi-gcc,来帮助您构建,调试和优化您的本地代码。您可以在这个网站上下载 Android NDK 的最新版本,然后按照文档的指导来使用 arm-eabi-gcc 编译器。GNU Arm Embedded Toolchain Downloads:这是 GNU Arm Embedded Toolchain 的官方网站,它是一个免费的、开源的、用于 C、C++ 和汇编编程的工具集。它支持 32 位的 ARM Cortex-A、ARM Cortex-M 和 ARM Cortex-R 处理器系列。它可以在 Windows、Linux 和 Mac OS X 操作系统上进行嵌入式软件开发。您可以在这个网站上下载该工具链的最新版本,也可以找到源代码包和安装说明。ARM-Linux 交叉编译工具链安装_arm-linux-gcc交叉编译工具链安装-CSDN博客:这是一个 CSDN 博客的网页,它介绍了如何在 Linux 系统上安装 arm-linux-gnueabihf-gcc 交叉编译工具链,它是由 Linaro 公司基于 GCC 推出的一个工具链,可以用于编译 ARM(32 位)系统中所有环节的代码。ARM交叉编译工具链 gnueabi、none-eabi、arm-eabi、gnueabihf、gnueabi区别-CSDN博客:这是一个 CSDN 博客的网页,它解释了不同的交叉编译器的命名规则,包括 gnueabi、none-eabi、arm-eabi、gnueabihf、gnueabi 等后缀的含义和区别。交叉编译学习笔记(二)——交叉编译器的命名规则-腾讯云开发者社区-腾讯云:这是一个腾讯云开发者社区的网页,它也介绍了交叉编译器的命名规则,以及如何选择合适的交叉编译器。 arm-eabi-gcc 交叉编译器

Required request parameter ‘***‘ for method parameter type String is not present

今天在学习 SpringBoot 的过程中遇到了这个问题。 问题背景 今天想实现一个更改用户头像的功能,Controller 层代码如下 @PatchMapping("/updateAvatar") public void updateAvatar (@RequestParam String url){ userService.updateAvatar(url); } 在调用该功能的时候出现了 Required request parameter ‘url’ for method parameter type String is not present 这个错误。 原因及解决 如图,前端发送请求时携带的参数名称为 avatarUrl,而我在 controller 层接受时用的 url,导致后端接受不到名为 url 的参数。 可以将 controller 层对应代码改成与请求参数相同 @PatchMapping("/updateAvatar") public void updateAvatar (@RequestParam String avatarUrl){ userService.updateAvatar(avatarUrl); } 也可以在 @RequestParam 上添加 value 属性,表明收到的参数和前端请求时携带的参数名称相同 @PatchMapping("/updateAvatar") public void updateAvatar (@RequestParam(value = "avatarUrl" String url){ userService.updateAvatar(url); }

table表格自动循环滚动

实现效果: 自动循环滚动 功能点: 1. 当表格内容超出时,自动滚动,滚动到最后一条之后在从头滚动。 2. 鼠标移入表格中,停止滚动;移出后,继续滚动。 1.vue-seamless-scroll依赖的使用(不太推荐) <vue-seamless-scroll :data="detailData" :class-option="classOptionThree" class="warp"> <table style="width:100%; height:90%" cellspacing="0" cellpadding="0"> ...... </table> </vue-seamless-scroll> 局部引入或全局引入后,用组件包住要滚动的表格,并将表格数据传进去。 参数:detailData是表格数据数组,classOptionThree是滚动的参数, computed: { classOptionThree() { return { step: 0.2, // 数值越大速度滚动越快 limitMoveNum: 2, // 开始无缝滚动的数据量 this.dataList.length hoverStop: true, // 是否开启鼠标悬停stop direction: 1, // 0向下 1向上 2向左 3向右 openWatch: true, // 开启数据实时监控刷新dom singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1 singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3 waitTime: 1000, // 单步运动停止的时间(默认值1000ms) }; }, }, 这个实现效果是表头也会跟着滚动,要想表头不滚动很简单,利用两个表格组件,

SpringBoot中如何优雅地使用重试

1 缘起 项目中使用了第三方的服务, 第三方服务偶尔会出现不稳定、连接不上的情况, 于是,在调用时为了保证服务的相对高可用,添加了超时连接重试, 当连接第三方服务超时时,多重试几次,比如3次,三次后仍连接不上,抛出异常, 在实际的测试过程中,重试一次即可连接到第三方服务, 提高了服务的可用性。 2 spring-retry Spring提供了重试项目:spring-retry,用于处理项目中需要重试的方法, spring-retry中提供了自定义参数,如重试次数、指定重试情况、重试延迟时间等, 满足不同的重试场景。 2.1 小插曲:试错过程 搜索SpringBoot如何使用重试注解时,发现需要使用spring-retry这个项目,在Maven仓库搜索了一下spring-retry,发现有多个版本,如下图,选择了最新版本2.0.4,启动项目时发现,无法运行。 环境: Java8 SpringBoot2.4.5 <!-- https://mvnrepository.com/artifact/org.springframework.retry/spring-retry --> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> <version>2.0.4</version> </dependency> 异常信息如下,版本不一致,进入spring-retry项目,查看项目配置。 java: 无法访问org.springframework.retry.annotation.Backoff 错误的类文件: /D:/install/maven/apache-maven-3.8.8/my-repository/org/springframework/retry/spring-retry/2.0.4/spring-retry-2.0.4.jar!/org/springframework/retry/annotation/Backoff.class 类文件具有错误的版本 61.0, 应为 52.0 请删除该文件或确保该文件位于正确的类路径子目录中。 查看spring-retry项目的配置文件,发现java版本为17,所以,使用java8无法启动项目, 因此,需要选择spring-retry对应Java8的版本。 2.2 正确过程 2.2.1 配置依赖 不指定spring-retry版本,Maven会自动下载合适的版本,本次自动下载的版本为1.3.1。 <!-- https://mvnrepository.com/artifact/org.springframework.retry/spring-retry --> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> 2.2.2 重试注解@Retryable 为方法添加@Retryable注解,即可在方法遇到异常时,重试指定次数。 常用参数如下,如有其他开发需求,可继续查看源码中的其他参数。 序号参数描述1value触发重试的异常情况2maxAttempts最大重试次数,默认重试3次3backoff补偿机制,delay重试延迟时间,单位:毫秒;multiplier延迟时间比例,延迟的具体时间为delay*multiplier(multiplier>0时生效,默认multiplier为0),当multiplier为0时,延迟时间即为delay 2.2.3 添加启动注解@EnableRetry 启动类中添加开启重试注解:@EnableRetry 配置样例如下: 启动重试@EnableRetry后,Spring会全局启动重试注解@Retryable,在执行重试方法时,通过CGLIB代理方法,根据注解的元数据进行重试,EnableRetry源码如下: org.springframework.retry.annotation.EnableRetry 2.2.4 测试重试 重试结果: 重试参数:5次,延迟:2秒,比例:2 重试间隔: 第二次:第一次~第二次:2秒 第三次:第二次~第三次:2 * 2=4秒

深入理解对象与垃圾回收机制

1、虚拟机中对象创建过程 1.1 对象创建过程 当我们使用 new 创建一个对象时,在 JVM 中进行了如下操作: 类加载:把 class 加载到 JVM 运行时数据区的过程。可以通过本地文件的形式,也可以通过网络加载。 检查加载:首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查类是否已经被加载、解析和初始化过。符号引用 :以一组符号来描述所引用的目标,比如 String 类的符号引用是全类名 java.lang.String。 分配内存:从堆内存中划分出一部分给新创建的对象。划分内存有两种方式:指针碰撞与空闲列表。 内存空间初始化:并不是执行类的构造方法的初始化,而是对变量赋默认初始化的值,如 int 型赋为 0,boolean 类型设置为 false。这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。 设置:接下来,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息(Java classes 在 Java hotspot VM 内部表示为类元数据)、对象的哈希码、对象的 GC 分代年龄等信息,这些信息存放在对象头之中。 对象初始化:在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从程序员的视角来看,对象创建才刚刚开始,所有的字段都还为零值。所以,一般来说,执行 new 指令之后会接着把对象按照程序员的意愿进行初始化(调用构造方法),这样一个真正可用的对象才算完全创建完成。 下面对部分过程做一个详细解释。 分配内存的方式 如果 Java 堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间的方向挪动一段与对象大小相等的距离,这种分配方式称为指针碰撞: 如果 Java 堆中的内存并不是规整的,已使用的内存和空闲的内存相互交错,那就没有办法简单地进行指针碰撞了,虚拟机就必须维护一个列表,记录上哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录,这种分配方式称为空闲列表: 堆中的内存是否规整,取决于使用的垃圾回收算法是否在回收完垃圾后对内存进行压缩整理,如果进行压缩整理那么内存就是规整的。 分配内存时的线程安全问题 内存分配为了提高效率会使用多线程进行分配,这就会涉及到并发安全问题。解决线程安全问题,这里使用 CAS 操作或者本地线程分配缓冲。 本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),它类似于 ThreadLocal,当有多个线程需要进行创建对象操作时,系统一般会在堆的 Eden 区中为每一个线程开辟一个专属的空间用于对象创建。这样既避免了线程安全问题,又省去了 CAS 操作带来的性能损耗: 具体来说,TLAB 把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在 Java 堆的 Eden 区中预先分配一小块私有内存,即 TLAB。JVM 在线程初始化时,同时也会申请一块指定大小的内存,只给当前线程使用,这样每个线程都单独拥有一个 Buffer,如果需要分配内存,就使用自己私有的分配指针在自己的 Buffer 上分配,这样就不存在线程竞争的情况,可以大大提升分配效率。

序列化基础

1、简介 对象序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象。它允许把内存中的 Java 对象转换成平台无关的二进制流(序列化,也称编码),并持久地保存在磁盘上或通过网络把这种二进制流传输到另一个网络节点,其它程序获得这种二进制流也可以把它恢复成原来的 Java 对象(反序列化,也称解码)。这样就使得对象可以脱离程序的运行而独立存在。 序列化的使用场景有: 本地存储:将对象数据永久的保存在文件或者磁盘中。网络传输:将对象数据在网络上进行传输。由于网络传输是以字节流的方式对数据进行传输的,因此序列化的目的是将对象数据转换成字节流的形式。进程间通信:在 Android 中,对象数据在进程之间传递(如 Activity 之间传递数据),或者 Intent 之间传递复杂的数据类型时(基本数据类型直接传不用序列化)。 Android 中常用的序列化方案:Serializable,Parcelable,Json,Xml,Protocol buffer。 合理的选择序列化方案,可以从以下方面考虑: 通用性:是否跨平台、跨语言。流行程度(很少人使用的协议往往意味着昂贵的学习成本)。健壮性:bug 要少。可调试性/可读性:Xml 可读性高。性能:时间、空间成本。可扩展性/兼容性安全性/访问限制:Android 的 Parcelable 曾有安全漏洞:漏洞预警 | Android系统序列化、反序列化不匹配漏洞 2、Serializable & Externalizable 接口 Serializable 是 Java 提供的一个标记接口,它只是表明该类的实例可以序列化,无须实现任何方法。Externalizable 接口是 Serializable 的子接口,其内部定义了 writeExternal(ObjectOutput) 和 readExternal(ObjectInput) 两个方法: public interface Serializable { } public interface Externalizable extends java.io.Serializable { void writeExternal(ObjectOutput out) throws IOException; void readExternal(ObjectInput in) throws IOException, ClassNotFoundException; } 我们先关注 Serializable 接口。 2.1 Serializable 基本使用 序列化时需要用 ObjectOutputStream 的 writeObject(OutputStream),反序列化时用 ObjectInputStream 的 readObject():

JVM 内存管理深度剖析

1、JVM 基础知识 1.1 JVM 与操作系统的关系 JVM 能识别 class 后缀的文件,并且能够解析它的指令,最终调用操作系统上的函数,完成指定操作。操作系统并不认识这些 class 文件,是 JVM 将它们翻译成操作系统可识别的机器码,最终由操作系统执行这些机器码。 Java 具有跨平台、跨语言的特性,也是因为 JVM 可以把 Java 字节码、Kotlin 字节码、Groovy 字节码等翻译成可以被 Linux、Windows、Mac 系统识别的机器码。一个 JVM 可以识别不同语言的字节码,但是只能将它们翻译成某一种系统能识别的机器码,不同的系统需要使用不同的 JDK,对应的 JVM 只能在该种系统上运行。 1.2 Java SE 体系架构 JVM 与 Java 提供的基础类库(如文件操作、网络连接和 IO 等)构成了 JRE,JRE、工具及其 API 和 Java 语言构成了 JDK。JDK 运行在 Linux、Windows 等平台之上。 注意 JVM 仅仅是一个“翻译”,Java 程序想要运行还需要基础类库 JRE,如需实现更多额外功能,还需要各种工具(由 JDK 提供,如 javac、javap、java 和 jar 等)。 1.3 JVM 整体 上图给出了 Java 程序的执行过程: 经过 javac 编译成为 class 字节码文件JVM 中的 ClassLoader 将 class 文件加载到运行时数据区(JVM 管理的内存)内的方法区中执行引擎执行这些 class 文件,将其翻译成操作系统相关的函数。这里有两种执行方式:解释执行(解释一行,执行一行)或 JIT 执行(将热点代码,即执行次数较多的代码或方法直接编译为本地代码以提高执行速度) Java 之所以能跨平台,就是由于 JVM 的存在。Java 的字节码,是沟通 Java 语言与 JVM 的桥梁,也是沟通 JVM 与操作系统的桥梁。

67_Pandas将切片应用于字符串,以提取任意位置和长度的部分

67_Pandas将切片应用于字符串,以提取任意位置和长度的部分 Python 字符串(内置类型 str)方法应用于 pandas.DataFrame 列(= pandas.Series),请使用 .str(str 访问器)。 例如,可以使用 str.match() 和 str.extract() 使用正则表达式提取字符串的一部分。 在这里,将介绍如何使用切片从任意位置(例如开头或结尾)提取任意长度(字符数)的字符串,并生成新字符串。 04_Pandas获取和修改任意位置的值(at,iat,loc,iloc) 将切片应用于 pandas 中的字符串列 提取第一个字符提取最后一个字符通过指定增量(步长)提取任意位置提取一个字符添加为 pandas.DataFrame 中的列 将数字转换为字符串并应用切片 以下面的 pandas.DataFrame 为例。 import pandas as pd df = pd.DataFrame({'a': ['abcde', 'fghij', 'klmno'], 'b': [123, 456, 789]}) print(df) # a b # 0 abcde 123 # 1 fghij 456 # 2 klmno 789 print(df.dtypes) # a object # b int64 # dtype: object 将切片应用于 pandas 中的字符串列 可以使用 .

Android 虚拟机与类加载机制

1、Dalvik 虚拟机 Android 应用程序运行在 Dalvik/Art 虚拟机上,并且每一个应用程序都有一个单独的 Dalvik/Art 虚拟机实例。 1.1 JVM 与 Dalvik Dalvik 虚拟机也算是一个 Java 虚拟机,它是按照 JVM 虚拟机规范实现的,二者的特性差不多,不过还是有一些区别的: 执行的指令集不同:Java 虚拟机执行的是 class 文件,Dalvik 虚拟机执行的是 dex 文件Java 虚拟机的指令集基于堆栈,Dalvik 虚拟机的指令集基于寄存器JDK 1.8 默认垃圾回收器是 Parallel Scavenge(年轻代)+ ParallelOld(老年代),而 Dalvik 默认垃圾回收器是 CMS DEX(Dalvik Executable Format)是专为 Dalvik 设计的一种压缩格式,它是很多 class 文件处理压缩后的产物,最终可以在 Android 运行时环境执行。 基于栈的虚拟机 基于栈的虚拟机会给每一个运行的线程分配一个独立的栈(虚拟机栈,是 JVM 运行时数据区的五大组成部分之一)。栈中记录了方法调用的历史,每有一次方法调用,栈中便会多一个栈桢。最顶部的栈桢称作当前栈桢,代表当前执行的方法。基于栈的虚拟机通过操作数栈进行所有操作。示意图如下: 对于一段很简单的代码,可以通过查看字节码文件查看它的指令: 指令含义: ICONST_1:将 int 类型常量 1 压入操作数栈位置 1ISTORE0:将栈顶 int 类型值存入局部变量表位置 0。test() 是一个静态方法,因此局部变量表就不用把位置 0 预留出来保存 thisIADD:执行 int 类型的加法 这些指令的执行过程图如下: 基于寄存器的虚拟机 寄存器是 CPU 的组成部分,是有限存储容量的高速存储部件,它们可用来暂存指令、数据和地址。

如何解决Java应用程序的Jar包冲突问题,看这一篇就够了

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、Jar包冲突问题 1. 什么是Jar包冲突问题 1.1 同一个Jar包出现了多个不一样版本 1.2 同一个类出现在多个不一样Jar包中 2. 为什么会产生Jar包冲突 2.1 maven仲裁机制 2.2 Jar包的加载顺序 3. Jar包冲突会导致什么问题 二、解决方案 1、问题排查和解决 2、如何有效避免 2.1 良好的习惯:依赖管理 2.2 冲突检测插件 总结 前言 我们在java应用程序的编译或者运行时可能会遇到抛出java.lang.ClassNotFoundException、java.lang.NoSuchMethodError、java.lang.NoClassDefFoundError这类的异常。这类异常一般都是jar包冲突导致的。那么jar包冲突的原因是什么?如何解决jar包冲突呢?我们一起来看下。 一、Jar包冲突问题 1. 什么是Jar包冲突问题 Jar包冲突问题的本质:Java应用程序因某种因素,加载不到正确的类而致使其行为跟预期不一致。 具体来讲可分为两种状况: 1)第一类Jar包冲突问题:应用程序依赖的同一个Jar包出现了多个不一样版本,并选择了错误的版本而致使JVM加载不到需要的类或加载了错误版本的类; 2)第二类Jar包冲突问题:一样的类(类的全限定名彻底同样)出现在多个不一样的依赖Jar包中,即该类有多个版本,并因为Jar包加载的前后顺序致使JVM加载了错误版本的类。 这两种状况所致使的结果实际上是同样的,都会使应用程序加载不到正确的类,那么其行为就会跟预期不一致了,下面对这两种类型进行详细分析。 1.1 同一个Jar包出现了多个不一样版本 随着Jar包迭代升级,应用程序所依赖的开源的或公司内部的Jar包工具都会存在若干不一样的版本,而版本升级天然就避免不了类的方法签名变动,甚至于类名的更替,而当前的应用程序依赖特定版本的某个类M ,因为maven的传递依赖而致使同一个Jar包出现了多个版本,当maven的仲裁机制选择了错误的版本时,而刚好类M在该版本中被去掉了,或者方法签名改了,致使应用程序因找不到所需的类M或找不到类M中的特定方法,就会出现第一类Jar冲突问题。可总结出该类冲突问题发生的如下三个必要条件: 因为maven的传递依赖致使依赖树中出现了同一个Jar包的多个版本该Jar包的多个版本之间存在接口差别,如类名更替,方法签名更替等,且应用程序依赖了其中有变动的类或方法maven的仲裁机制选择了错误的版本 1.2 同一个类出现在多个不一样Jar包中 一样的类出现在应用程序所依赖的两个及以上的不一样Jar包中,这会致使什么问题呢?我们知道,同一个类加载器对于同一个类只会加载一次(多个不一样类加载器就另说了,这也是解决Jar包冲突的一个思路,后面会谈到),那么当一个类出现在多个Jar包中,假设有 A 、 B 、 C 等,因为Jar包依赖的路径长短、声明的前后顺序或文件系统的文件加载顺序等缘由,类加载器首先从Jar包 A 中加载了该类后,就不会加载其他Jar包中的这个类了,那么问题来了:若是应用程序此时需要的是Jar包 B 中的类版本,而且该类在Jar包 A 和 B 中有差别(方法不一样、成员不一样等等),而JVM却加载了Jar包 A 的中的类版本,与期望不一致,自然就会出现各类诡异的问题。 从上面的描述中,能够发现出现不一样Jar包的冲突问题有如下三个必要条件: 同一个类 M 出现在多个依赖的Jar包中,为了叙述方便,假设仍是两个: A 和 BJar包 A 和 B 中的该类 M 有差别,不管是方法签名不一样也好,成员变量不一样也好,只要能够形成实际加载的类的行为和指望不一致都行。若是说Jar包 A 和 B 中的该类彻底同样,那么类加载器不管先加载哪一个Jar包,获得的都是一样版本的类 M ,不会有任何影响,也就不会出现Jar包冲突带来的诡异问题。加载的类 M 不是所指望的版本,即加载了错误的Jar包 2.

【IJCAI2022】Uncertainty-Guided Pixel Contrastive Learning for Semi-Supervised Medical Image Segmentat

Uncertainty-Guided Pixel Contrastive Learning for Semi-Supervised Medical Image Segmentation, IJCAI2022 论文:https://www.ijcai.org/proceedings/2022/0201.pdf 代码:https://github.com/taovv/UGPCL 简介 论文将对比学习引入半监督分割,并提出了一种新的不确定性引导的半监督医学图像分割像素对比学习方法。具体来说,为每个未标记的图像构建一个不确定性图,然后重新移动不确定性图中的不确定性区域,以降低噪声采样的可能性。不确定性图由精心设计的一致性学习机制确定,该机制通过鼓励来自两个不同解码器的一致性网络输出来生成对未标记数据的全面预测。此外,论文认为由图像编码器学习的有效全局表示对于不同的几何变换应该是等变的,于是构造了一个等变对比损失来增强编码器的全局表示学习能力。 动机 现有方法主要通过构建可信的伪标签 或扰动输入强制预测一致性来利用未标记数据,但,使得每个像素的分类独立,忽略了图像像素(或特征)之间的内部相关性。 对比学习的思想在于,相似样本的表征应该是相似的,不同类型样本的表征应是不同的。 图像分割中,相似的像素分布密集,如何构建适用于像素级的对比学习呢,常见做法是使用伪标签构建对比样本。但伪标签构建样本可能与实际语义类别不一致,可能导致对比学习中的噪声采样问题。且,像素对比学习只建立了局部像素的关联,忽略了全局表示信息的学习。 因此,论文的目标在于: 解决使用伪标签的对比学习的噪声采样问题,增强编码器的全局表示学习能力。 为此,论文提出了一种基于不确定性的对比学习方法。图1显示了本文方法的核心思想。 对于未标记的数据,使用不确定性图来引导伪标签采样的区域,并减少错误样本的数量。然后计算样本对比损失,以优化网络,减少预测的不确定性区域。为了获得更好的不确定性图,设计了一种具有CNN解码器和Transformer解码器的一致性学习策略,该策略可以利用两个解码器之间的结构差异从不同的角度获得精确的预测。此外,分割模型应该具有识别几何变换的能力,定义了一个等变对比损失,通过在表示学习阶段添加变换类别预测,迫使网络学习几何变换的识别信息。 方法 图2:方法概述。不同颜色的箭头表示不同数据的处理流程。特别是,对于未标记的数据,确定性标签是通过使用伪标签和不确定性映射的掩码选项获得的。对于像素对比学习,通过未标记数据的确定性标签和标记数据的基本事实来选择对比锚。 DL和DU中的图像先经过几何变换,再输入编码器网络以提取多尺度特征。再把这些特征发送到三个分支中:一致性学习分支、不确定性引导的对比学习分支和等变对比学习分支。 Consistency Learning,一致性学习分支,提出一个异质一致性网络来预测分割结果,由监督损失Lsup和一致性损失Lcon驱动。uncertainty-guided contrastive learning, 不确定性引导的约束学习分支,建立一个记忆队列,以保留足够的样本用于约束学习。记忆队列中样本的选择取决于DL的标签和DU的确定性标签。对于所选样本,施加像素级的对比损失Lc,以使同一类的像素彼此靠近并且使不同类的像素相互远离。equivariant contrastive learning,等变对比学习分支,对所有标记和未标记的数据进行几何变换类别预测,并设计一个等变对比损失Le以迫使编码器对几何变换具有鲁棒性。 整体框架的总优化目标是: Consistency Learning 设计一个CNN解码器和Transformer解码器结构,实现两个目标: 使用未标记的数据来促进分段网络的学习,从网络输出中获得可靠的不确定性估计。 研究表明,使用协同训练策略可以获得更好的分割性能,其核心思想是从不同的角度做出不同的分类预测,然后将预测的差异作为不确定性估计的衡量标准。本文利用了变换器解码器和CNN解码器之间的先天差异。具体地说,构造了一个非一致的预测器来约束两个解码器产生一致的预测,然后使用均值预测的熵来估计不确定性图。 可以从两个解码器获得两个预测的概率分布pt和pc。对于标记数据,使用真实标签gt来计算监督分割损失:分割损失由CE和Dice取均值。 对于无标记数据,使用距离度量来计算一致性损失,使用MSE作为距离度量。 Uncertainty-Guided Contrastive Learning 使用交叉熵损失容易使得每个像素的分类是独立的,忽略了像素之间的关系。为此,设计了一种像素级对比学习机制,将同一类别(语义标签)的像素分类为正样本,将不同类别的像素归类为负样本。像素之间的关系是通过在嵌入空间中减小正样本之间的距离和扩大负样本之间的间距来建立的。为了有效地将未标记数据用于像素级对比学习,估计了未标记像素的不确定性,并选择确定性较高的像素作为对比学习的锚点。 Mask Uncertainty Region. 我们选择预测熵作为度量来近似不确定性。具体而言,首先计算预测结果的平均值,然后计算通道维度中每个像素的概率分布的熵。然后,将不确定性较大的区域去除,获得确定的伪标签。 H为不确定性标签的阈值,yp是确定的伪标签。 Anchor Sampling. 使用标记图像的标签和未标记图像的确定性伪标签作为使用对比样本的基础。由于原始图像分辨率太大,原始图像大小的对比学习成本很高,并且像素的原型向量包含较少的语义信息。因此,在分辨率较低的特征空间中使用对比学习。 首先,从编码器中提取的特征将被嵌入到D维空间中,其中每个D维特征向量表示。然后,将标签下采样到相同的分辨率,为每个原型向量指定类别,并且不对不确定性区域中的向量进行采样。采用随机抽样的策略,每个类别抽固定数量。如果同一类别的样本数量较少,将对其他类别的锚进行采样。对比负样本的数量极大地影响了对比学习的性能,但大量的负样本会产生大量的开销。一个更好的解决方案是使用固定大小的外部存储器来存储采样样本,并通过训练更新存储内容。论文设置了一个内存队列来存储收集到的样本。在每次迭代中,随机选择的样本被用作锚来计算对比损失,然后它们被更新到内存队列中。 Pixel Contrastive Loss. 原型向量及其像素类别保存在样本队列中。使用流行的InfoNCE损失函数来计算对比损失。在每次迭代中,随机抽取M个锚,并计算每个锚的对比损失。然后将所有锚的损失平均为整体对比损失。具体计算如下 其中Pi和Ni表示像素i的正样本和负样本的原型向量集合。vi是像素i的原型向量,vi+是正原型向量,vi−是负向量,τ是温度超参数。 Equivariant Contrastive Loss 本文建议分割任务所需的有效特征表示对不同的几何变换应该是等变的(或有区别的)。 在分段模型的表示学习中添加等变对比损失,以学习全局信息。具体来说,将分割模型定义为编码器-解码器形式。对于图像xi,当它经过某种几何变换G(·)时,相应的分割结果也会发生变化,即: 添加一个分类预测器来预测几何变换的判别结果。等比对比损失为: 实验 代码 ugpcl_trainer.py # https://github.

网络视频播放卡顿原因分析

一、问题描述 某项目通过拉摄像机rtsp流转rtmp/http-flv/ws-flv的方案,使用户可以在网页中观看摄像机的视频画面。在 观看视频时偶发出现卡顿现象。 二、卡顿现象分析和解决 此问题涉及的原因较多,所以得考虑各环节的问题可能性,并根据现场实际情况进行处理。整个项目的视频链路为摄像机(rtsp服务器) -> 推流端(将摄像机rtsp转rtmp) -> 流媒体服务器(转协议,将rtmp转为http-flv/ws-flv) -> 外网服务器(提供互联网访问连接的主机电脑,让用户可以在外网观看最终转出来的视频)。 可以看到链路比较多,当出现卡顿问题时需要从摄像机排查到推流端、流媒体服务器......外网再到播放器。我们可以一步步通过ffplay/vlc等播放器播放摄像机rtsp,内网播放http-flv/ws-flv,再到外网播放转出来的流来一步步排查是哪个链路出现问题。 (一)推流端 1.推流端硬件条件限制 使用推流工具(比如FFmpeg)推流(转码) “ 时,码率、帧率或编码档位设置得过高,但硬件条件存在限制(推流软件 所在电脑的 CPU 性能较差),导致编码速度变慢,无法达到流畅播放的帧率要求。 如果推流端所在电脑的整体 CPU 使用率超过80% ,那么视频的采集和编码都会受到影响,无法正常发挥作用;如果其 CPU 使用率达到 100%,那么推流端本身就已经很卡,观众端要有流畅的观看体验显然是不可能的。在Windows上可以使用任务管理器,Linux上使用top命令查看进程的CPU使用率。 解决方法: 尝试降低码率、帧率的设置,检查卡顿现象是否有好转。如果发生好转,可以考虑升级推流端所在电脑的硬件配置;或者不转码仅仅进行转封装 进行推流。 2.系统资源占用 检查推流端 所在电脑后台是否运行了大量的程序,建议删除和停止正在运行的程序,空出资源。 3.推流帧率过低 人眼识别为流畅的视频需要 FPS 每秒 15 帧以上。如果 FPS 低于 10 帧,画面就会出现较明显的卡顿。如无特殊情况,尽量将视频帧率设置在每秒15 帧之上,如果摄像机画面本身变化就很少,如静态画面或PPT 播放等场景,则不受该原因影响 。虽然视频的帧率越高画面流畅感越强,但是帧率超过每秒 30 帧 后,人眼就无法识别出画面的效果,帧率增加也会增加视频传输的带宽成本,建议合理设置该参数。 解决方法: 在推流指令中更改推流的帧率;或者更改摄像机自带配置网页中的设置,在里面更改帧率。 (二)流媒体服务器端 1.GOP缓存功能 为了保证视频的秒开以及降低视频的卡顿,一般的流媒体服务器默认会缓存数秒的数据,这一般叫 GOP缓存功能。比如缓存 180 秒的帧数据 , 任何终端播放的时候都是从 180 秒前进行播放 , 这样就至少保证 不会出现卡顿,但这样做延时会很大。部分流媒体服务器,比如开源的zlmediakit 并没有该功能。 2.自适应码率技术 自适应码率技术可以: 1. 让播放体验更加智能。例如,用户在一个不确定的网络环境下,不知道什么 清晰度最合适,选择高清晰度,卡了;选择低清晰度,画质体验又不好。自适应码率就是要解决这个选 择问题,智能匹配最合适的清晰度,避免用户自己反复去尝试;2.

每日一题--删除链表的倒数第 N 个结点

破阵子-晏殊 燕子欲归时节,高楼昨夜西风。 求得人间成小会,试把金尊傍菊丛。歌长粉面红。 斜日更穿帘幕,微凉渐入梧桐。 多少襟情言不尽,写向蛮笺曲调中。此情千万重。 目录 题目描述: 思路分析: 方法及时间复杂度: 法一 双指针(经典解法) 法二 计算链表长度(暴力解法) 法三 栈 法四 哈希表 法五 vector 法六 递归(烧脑解法) 个人总结: 题目描述: 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode) 思路分析: 此题要求是删除倒数第N个结点,那么主要的就是找到倒数第N个结点,然后让该节点的前一个指向该结点的下一个。 那么这道题便有五种以上的解法,核心就是找到要删的那个结点。 方法及时间复杂度: 法一 双指针(经典解法) 定义两指针:fast=head,slow=head。 fast先走n步,然后fast跟slow同时走。 直到fast走到空,此时slow 就到删除的结点。原理:设链表长L,快指针共走L步,慢指针走L-n步。故此方法由法二得来。 由于这题是删除该结点,这得需要删除结点的前继结点。所以让slow少走一步。可以直接开辟一个虚拟结点让slow=dummy。 这样solw就可以到达删除结点的前一个结点了。然后像思路分析那样操作。代码如下: class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { ListNode* dummy=new ListNode(0,head); ListNode* fast=head,*slow=dummy; while(n--){ fast=fast->next; } while(fast){ fast=fast->next; slow=slow->next; } slow->next=slow->next->next; ListNode* ans=dummy->next; delete dummy; return ans; } }; 时间复杂度O(L),链表长度为L。

Vue项目的创建、运行与端口号修改

前言:Vue-cli是Vue官方提供的一个脚手架,用于快速生成一个Vue的项目模板,依赖于NodeJS环境 NodeJS下载:NodeJS安装下载 Vue-cli下载:Vue-cli下载 一.Vue图形化创建项目 1.建立一个文件夹,保存Vue项目 2.在该文件夹的目录上输入cmd打开命令行 3.令行输入vue ui打开Vue项目管理器 4.点击创建-在此创建新项目 5.选择预设模板 6.选择插件功能 7.选择Vue版本 最后点击创建项目,不保存预设模板 等待项目创建完成(大概3分钟左右),当出现以下信息时表示项目创建完成。 生成的Vue项目文件夹内容如下: Src文件夹下的目录 二.VsCode运行Vue项目 在创建完Vue项目后,使用Vscode运行Vue项目步骤如下: 1.使用Vscode打开Vue创建的文件夹项目 Vscode—文件–打开文件夹—选择Vue创建的目录 显示的文件夹内容应当如下: 如果菜单栏左下角没有npm选项,则点击资源管理器旁边的三个小点将npm打开 3.运行Vue项目 运行界面: 点击蓝色的链接,即可跳转出前端页面(App.vue) 三.停掉Vue项目并重新启动 1.Ctrl + C停止服务 2.输入y确认停止 3.成功停止后,按之前的方法启动即可 四.Vue项目端口号的修改 Vue自动给我们项目的访问地址端口是8080,如果要修改,则需要进行以下代码操作 1.在vue.config.js文件中修改代码,添加devServer的port属性 const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, devServer:{ port:7000 //要修改的端口号 } }) 停掉服务重启后,端口即可修改

Android ANR log trace日志文件分析

什么是ANR? ANR:Application Not Responding,即应用无响应 ANR日志Trace文件获取 系统生成的Trace文件保存在data/anr,可以用过命令adb pull data/anr/取出 traces.txt只保留最后一次ANR的信息,Android系统有个DropBox功能功能,它能记录系统出现的crash错误.因此保留有发生过的ANR的信息.(log路径:/data/system/dropbox) 获取系统crash log: adb shell dumpsys dropbox --print >>log.txt Trace文件怎么生成的? 当APP(包括系统APP和用户APP)进程出现ANR、应用响应慢或WatchDog的监视没有得到回馈时, 系统会dump此时的top进程,进程中Thread的运行状态就都dump到这个Trace文件中了. 导致ANR的常见几种情况: 1:Input dispatching timed out(5 seconds) 按键或触摸事件处理超时(一般是UI主线程做了耗时的操作,这类ANR最常见) 2:BroadcastTimeout(10 seconds) 广播的分发和处理超时(一般是onReceiver执行时间过长) 3:ServiceTimeout(20 seconds) Service的启动和执行超时 另外还有ProviderTimeout和WatchDog等导致的ANR.还有当系统内存或CPU资源不足时容易出现ANR,一般这种情况会有lowmemorykill的log打印. 应用ANR产生的时候,ActivityManagerService的appNotResponding方法就会被调用,然后在/data/anr/traces.txt文件中写入ANR相关信息. final void appNotResponding(ProcessRecord app, ActivityRecord activity, ActivityRecord parent, boolean aboveSystem, final String annotation) { // ... ... if (MONITOR_CPU_USAGE) { updateCpuStatsNow(); // 更新CPU使用率 } // ... ... final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true); // dumpStackTraces是输出traces文件的函数 File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids, NATIVE_STACKS_OF_INTEREST); String cpuInfo = null; if (MONITOR_CPU_USAGE) { updateCpuStatsNow(); // 再次更新CPU信息 synchronized (mProcessCpuTracker) { // 输出ANR发生前一段时间内的CPU使用率 cpuInfo = mProcessCpuTracker.

Android长截屏(滚动截屏)实现原理

Google原生Android系统到目前为止均没有长截屏这一功能,而对于用户而言,这是一个非常实用的功能,如聊天记录,新闻页面等较长的页面想通过一张图片的形式保存起来.好在国内主流手机厂商均已实现了该功能,接下来聊聊我们长截屏的实现原理. 长截屏原理概述: 我们简单的把一个屏幕分成三分,上中下,中间区域最大,中间区域也就是滑动区域;长截屏开始,我们截取顶部的图片保存到集合中,截取长度如下,然后每次滑动图片前截取中间部分图片保存到集合中,也就是滑动多少次就会有多少张中间区域图片,最后保存时,截取底部图片保存到集合中;随后把集合中的图片拼接起来就完成了长截屏 中间部分为滑动区域,也就是我们模拟手指在屏幕上滑动一个指定长度,这个长度也就是中间图片的长度.模拟滑动代码如下: // 模拟Down事件 MotionEvent tempDown = MotionEvent.obtain(downTime, eventTime, 0, toX, toY, 0); tempDown.setSource(4098); InputManager.getInstance().injectInputEvent(tempDown, Integer.valueOf(2)); // 模拟Move事件 MotionEvent tempMove = MotionEvent.obtain(downTime, eventTime, 2, toX, toY, 0); tempMove.setSource(4098); InputManager.getInstance().injectInputEvent(tempMove, Integer.valueOf(2)); // 模拟Up事件 MotionEvent tempUP = MotionEvent.obtain(downTime, eventTime, 1, toX, toY, 0); tempUP.setSource(4098); InputManager.getInstance().injectInputEvent(tempUP, Integer.valueOf(2)); injectInputEvent方法为@hide,没环境调用的可以通过反射调用: try { Class<?> ClassInputManager = Class.forName("android.hardware.input.InputManager"); Method[] methods = ClassInputManager.getMethods(); Method methodGetInstance = null; Method methodInjectInputEvent = null; Method method = methods[0]; for (int i = 0; i < methods.

Android开机向导setupwizard,设置系统语言,WiFi向导

Android的框架设计有考虑到开机向导这一场景,因此我们实现开机向导参考Android的Provision.apk Provision: MSM8976/repo/packages/apps/Provision 它的主要作用是作为开机引导用户进行一些基本设置.在原生的 android 系统中,provision非常的简单,只有一个空白的 activity,这个主要就是留给 厂商自己定制开机向导(像 OPPO,VIVO,小米等厂商会让你登陆和注册其账号帐号,连接WiFi等),因此我们得理解Android的设计意图而进行定制. <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.tomorrow_p.setupwizard"> <!--android:sharedUserId="android.uid.system"--> <original-package android:name="com.android.provision" /> <!-- For miscellaneous settings --> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <!--<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />--> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/setupwizard_AppTheme"> <activity android:name=".DefaultActivity" android:excludeFromRecents="true"> <intent-filter android:priority="1"> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.tomorrow_p.setupwizard.SimActivity"> <intent-filter> <action android:name="com.android.provision.SimActivity"></action> <category android:name="android.intent.category.DEFAULT"></category> </intent-filter> </activity> <activity android:name="com.tomorrow_p.setupwizard.OpenActivity"> <intent-filter> <action android:name="com.android.provision.OpenActivity"></action> <category android:name="android.intent.category.DEFAULT"></category> </intent-filter> </activity> </application> </manifest> 1.

四.Activity的启动流程-ActivityThread启动Activity的过程

Activity的启动一般分为普通Activity的启动,根Activity的启动.而根Activity是指应用启动的第一个Activity过程,所以也可以理解为应用的启动过程. 相关内容链接:android系统启动流程 应用的启动流程大致分为如下四个阶段: 一.应用进程(Launcher)调用ATMS系统进程的过程 二.ActivityTaskManagerService到ApplicationThread的调用过程 三.AMS向Zygote发送启动应用进程的过程 四.ActivityThread启动Activity的过程 Activity启动过程涉及到进程之间的关系: 四.ActivityThread启动Activity的过程 类名: android.app.ActivityThread.ApplicationThread ApplicationThread类可以看作是AMS所在进程(SystemServer进程)和应用进程通信的桥梁,通过Binder的方式来执行 ActivityThread主要用来处理Activity生命周期等一些逻辑,ActivityThread继承自抽象类ClientTransactionHandler,将以前ActivityThread里面的handleLaunchActivity、handleStartActivity、handleResumeActivity和handleStopActivity等方法抽取出来,作为ClientTransactionHandler类的抽象方法. 1. scheduleTransaction ApplicationThread继承自IApplicationThread.Stub,第二阶段中IApplicationThread的Binder调用就会执行到这里,这块代码比较简单,调用ActivityThread的scheduleTransaction方法,而ActivityThread是继承自抽象类ClientTransactionHandler, ActivityThread没有重写该方法,所以这里就会调用到ClientTransactionHandler的scheduleTransaction方法. @Override public void scheduleTransaction(ClientTransaction transaction) throws RemoteException { ActivityThread.this.scheduleTransaction(transaction); } 类名: android.app.ClientTransactionHandler: 2. scheduleTransaction void scheduleTransaction(ClientTransaction transaction) { transaction.preExecute(this); sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); } 类名: android.app.ActivityThread.H 3. handleMessage() class H extends Handler { public void handleMessage(Message msg) { // ... ... case EXECUTE_TRANSACTION: final ClientTransaction transaction = (ClientTransaction) msg.obj; mTransactionExecutor.execute(transaction); if (isSystem()) { // Client transactions inside system process are recycled on the client side // instead of ClientLifecycleManager to avoid being cleared before this // message is handled.

Android权限管理--权限类型

目录 1.普通权限(normal) 2.运行时权限(dangerous) 3.签名权限(signature) 4.特殊权限(privileged) 查看android权限的等级 判断应用是否拥有对应权限 Android 将权限分为不同的类型,包括安装时权限、运行时权限和特殊权限。每种权限类型都指明了当系统授予应用该权限后,应用可以访问的受限数据范围以及应用可以执行的受限操作范围。 1.普通权限(normal) 此类权限允许访问超出应用沙盒的数据和执行超出应用沙盒的操作。但这些数据和操作对用户隐私及对其他应用的操作带来的风险非常小。 2.运行时权限(dangerous) 运行时权限也称为危险权限,此类权限授予应用对受限数据的额外访问权限,并允许应用执行对系统和其他应用具有更严重影响的受限操作。因此需要先在应用中请求运行时权限,然后才能访问受限数据或执行受限操作。当应用请求运行时权限时,系统会显示运行时权限弹窗提示。 3.签名权限(signature) 当应用声明了其他应用已定义的签名权限时,如果两个应用使用同一证书进行签名,系统会在安装时向前者授予该权限。否则,系统无法向前者授予该权限。(注意:有些签名权限不适合第三方应用使用。) 该权限只需要在manifest中声明使用,同时应用和这类权限定义者拥有一样的签名系统就会默认授予应用这类权限;系统授予这类权限后应用无需像运行时权限一样动态申请。 4.特殊权限(privileged) 特殊权限与特定的应用操作相对应。只有平台和原始设备制造商 (OEM) 可以定义特殊权限。此外,如果平台和 OEM 想要防止有人执行功能特别强大的操作(例如通过其他应用绘图),通常会定义特殊权限。系统设置中的特殊应用访问权限页面包含一组用户可切换的操作。其中的许多操作都以特殊权限的形式实现。每项特殊权限都有自己的实现细节。系统会为特殊权限分配“appop”保护级别。 该权限只需要在manifest中声明使用,同时拥有系统签名且不是预置到 **/priv_app/ (如:system/priv-app)目录下,系统就会默认授予;如果应用是预置到 **/priv_app/ 目录下则需要在配置文件privapp-permissions-platform.xml中配置权限信息,否则系统不会授予权限,并且也会无法通过cts测试 查看android权限的等级 在系统源码中找到文件 /frameworks/base/core/res/AndroidManifest.xml ,这个文件中定义了系统权限等信息。 如 WRITE_MEDIA_STORAGE权限 具体如下: 权限名称:android.permission.WRITE_MEDIA_STORAGE 权限等级为:signature|privileged (该权限既是signature也是privileged权限) <!-- @SystemApi @TestApi Allows an application to write to internal media storage @hide --> <permission android:name="android.permission.WRITE_MEDIA_STORAGE" android:protectionLevel="signature|privileged" /> 如 READ_CONTACTS权限 具体如下: 权限名称:android.permission.READ_CONTACTS 权限等级为:dangerous (该权限为运行时权限,也就是需要应用去动态申请) <!-- Allows an application to read the user's contacts data.

李宏毅机器学习第十八周周报GAN2

文章目录 week 18 GAN2摘要Abstract一、Theory behind GAN1. 训练目的2. Wasserstein distance 二、文献阅读1. 题目2. abstract3. 网络架构3.1 Wasserstein Distance3.2 Wassertein GANs3.3 Gradient penalty 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程4.3.1 Difficulties with weight constraint4.3.2 单一数据集上训练随机架构4.3.3 LSUN上训练多种框架4.3.4 改进权重裁剪的性能4.3.5 CIFAR-10和LSUN的样本质量4.3.6 使用连续的生成器对离散数据进行建模 4.4 结论 三、WGAN小结参考文献 week 18 GAN2 注:关于wasserstein的详细解释见第二部分3.1 摘要 本文主要讨论了生成式对抗神经网络。首先,本文介绍了Original GAN的缺点。在此基础下,本文阐述了多种改进GAN的方案。例如,以Wasserstein distance为评价标准构建WGAN。其次本文展示了题为Improved training of wasserstein GANs的论文主要内容。这篇论文探讨了WGAN的结构,并给出了其在训练过程中难以收敛,或者收敛后效果不佳的原因。在此基础上,该文提出了基于gradient penalty的新框架,该框架能够充分利用网络容量以及降低梯度爆炸以及消失。最后,本文基于pytorch以及MNIST数据集实现了WGAN绘制手写数字。 Abstract This article mainly discusses Generative Adversarial Networks (GANs). Firstly, this article introduces disadvantage of Generative Adversarial Networks. Building upon this foundation, the article elucidates the improvement scenarios of GANs.

手撕AVL_二叉平衡树(图文并茂)

目录 前言 一 . AVL树的概念 二 . AVL树节点的定义 三 . AVL树的插入 1.插入节点 2.调节负载因子 四 . AVL树的旋转 1.左单旋 2.左右双旋 五 . AVL树性能分析 总结 前言 大家好,今天带大加手撕AVL树的插入 一 . AVL树的概念 二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年 发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。 一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树: 它的左右子树都是AVL树左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1) 如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在搜索时间复杂度。 二 . AVL树节点的定义 为了AVL树实现简单,AVL树节点在定义时维护一个平衡因子,具体节点定义如下: static class TreeNode{ int val; int bf; // 平衡因子 -> 当前节点的平衡因子=右子树高度-左子树的高度 TreeNode left;// 节点的左孩子 TreeNode right;// 节点的右孩子 TreeNode parent;// 节点的双亲 public TreeNode(int val){ this.val = val; } } 注意: 当前节点的平衡因子=右子树高度-左子树的高度。但是,不是每棵树,都必须有平衡因子,这只是其中的一种实现 方式。 三 . AVL树的插入 AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么AVL树的插入过程可 以分为两步:

番外篇Diffusion&Stable Diffusion扩散模型与稳定扩散模型

文章目录 Diffusion&Stable Diffusion扩散模型与稳定扩散模型摘要AbstractDiffusion Model扩散模型Forward Diffusion Process正向扩散过程噪声图像的分布封闭公式 Reverse Diffusion Process反向扩散过程loss function损失函数Loss Function of VAE model VAE模型的损失函数kl loss KL散度正则项 Variational Lower Bound变分下界UNet 扩散模型的速度问题 Stable Diffusion稳定扩散潜在空间潜在空间的扩散 条件作用/调节训练架构比较 参考文章 Diffusion&Stable Diffusion扩散模型与稳定扩散模型 摘要 本篇文章为阅读笔记,,主要内容围绕扩散模型和稳定扩散模型展开,介绍了kl loss、vae模型的损失函数以及变分下限作为扩展部分。扩散模型是一种生成模型,定义了一个逐渐扩散的马尔科夫链,逐渐项数据添加噪声,然后学习逆扩散过程,从噪声中构建所需的数据样本。稳定扩散模型在其基础上添加了编码器用以降维训练数据、降低训练成本,该模型亦添加了额外的文本嵌入向量,通过该向量模型得以根据文本生成图片。 主要内容参考deephub,“Diffusion 和Stable Diffusion的数学和工作原理详细解释”,https://zhuanlan.zhihu.com/p/597924053 Abstract This article is a reading note, the main content is around the diffusion model and stable diffusion model, and introduces the loss function of VAE model, KL loss and the variational lower bound as an extended part.

通信原理框图整理

文章目录 第一章 绪论模拟通信系统模型数字通信系统模型 第二章 信道调制信道和编码信道的划分 第三章 模拟调制系统相移法产生SSB信号有噪声的相干解调器倍频法产生WBFM 第四章 信源编码非均匀量化PCM系统框图增量调制波形及其编码 第五章 数字信号的基带传输第一类部分响应系统组成的框图眼图模型基带传输系统波形 第六章 数字信号的载波传输2ASK信号的解调2FSK产生原理框图2FSK解调器2FSK信号过零点检测法原理框图各点波形 2PSK模拟调相法产生绝对相移信号2PSK的解调相干解调鉴相器解调 2DPSK信号产生2DPSK相干解调2DPSK的差分相干解调调相法产生4PSK4PSK的相干解调调相法产生4DPSK4DPSK的差分相干解调 第七章 现代数字调制技术MSK调制器原理框图OQPSK的产生原理框图OQPSK的正交相干解调MQAM调制器与解调器 第八章 同步原理插入导频法发端插入导频法收端平方变换法提取载波科斯塔斯环法提取载波插入位定时导频接收(插入导频法提取位同步)微分整流法提取位同步信息包络检波法提取位同步信息延迟相干法提取位同步信号7位巴克码的R(j)与j的关系曲线7位巴克码的产生器7位巴克码识别器 第九章 信道编码(7,3)循环码编码器(7,3)循环码译码器 第一章 绪论 模拟通信系统模型 数字通信系统模型 第二章 信道 调制信道和编码信道的划分 第三章 模拟调制系统 相移法产生SSB信号 有噪声的相干解调器 倍频法产生WBFM 第四章 信源编码 非均匀量化PCM系统框图 增量调制波形及其编码 第五章 数字信号的基带传输 第一类部分响应系统组成的框图 眼图模型 基带传输系统波形 第六章 数字信号的载波传输 2ASK信号的解调 2FSK产生原理框图 2FSK解调器 2FSK信号过零点检测法 原理框图 各点波形 2PSK模拟调相法产生绝对相移信号 2PSK的解调 相干解调 鉴相器解调 2DPSK信号产生 2DPSK相干解调 2DPSK的差分相干解调 调相法产生4PSK 4PSK的相干解调 调相法产生4DPSK 4DPSK的差分相干解调 第七章 现代数字调制技术 MSK调制器原理框图 OQPSK的产生原理框图 OQPSK的正交相干解调 MQAM调制器与解调器 第八章 同步原理 插入导频法发端 插入导频法收端 平方变换法提取载波 科斯塔斯环法提取载波 插入位定时导频接收(插入导频法提取位同步) 微分整流法提取位同步信息 包络检波法提取位同步信息 延迟相干法提取位同步信号 7位巴克码的R(j)与j的关系曲线 7位巴克码的产生器 7位巴克码识别器 第九章 信道编码 (7,3)循环码编码器 (7,3)循环码译码器

图的建立基本操作

#include <stdio.h> #include <stdlib.h> #include <stdbool.h> // 添加头文件 #define MAX_VERTEX_NUM 100 //图中最大顶点数 //struct ArcNode* nextarc; //ArcNode* firstarc; //这两个是很有必要的,如果你没有这两个指针,你就无法判断当前的顶点是哪一个 // adj是邻接点,firstarc和nextarc分别代表当前和下一个点。 //图的邻接表存储结构定义 typedef struct ArcNode { int adjvex; //邻接点在数组中的位置下标 struct ArcNode* nextarc; //指向下一个邻接点的指针 } ArcNode; typedef struct VNode { char data; //顶点信息 ArcNode* firstarc; //指向第一个邻接点的指针 } VNode, AdjList[MAX_VERTEX_NUM]; //使用结构体嵌套的方式,把两个顶点还有边都给嵌套起来 typedef struct { AdjList vertices; //邻接表,也就是顶点的意思 int vexnum, arcnum; //顶点数和弧数 bool is_directed; //是否是有向图 } ALGraph; //查找顶点的第一个邻接点 int FirstAdjVex(ALGraph G, int v) { if (G.

googleplay应用提审

前置内容: 如果你的googleplay后台不是中文的,去你的google账号里设置一下: 如何修改谷歌账号的默认语言? https://baijiahao.baidu.com/s?id=1758765859536278761&wfr=spider&for=pc 很多网友在登录到谷歌账户后,由于所借助的IP不同,有时候登录之后显示的语言为英文、俄文或者其他文字,在外语界面下操作起来非常不顺畅,这时候就需要进到设置调整语言变成中文。很多小伙伴不清楚设置语言的具体位置,而且外文显示更增加了修改语言的困难性。本文一次性介绍整个修改默认语言的完整流程,供大家参考使用。 如果您还没有账号,或者不想操作修改默认语言流程,可以到shop.googleacc.net购买一个账号,登录后默认语言即为中文。 1、登录谷歌账户后,点击右上角圆圈,然后点击“Manage your Google Account”(如果是其他语言,位置相同); 2、下一步点击左侧的Personal info,然后下拉右侧界面,看到一个地球的图标,后面紧跟Language,点击这里。如果是手机界面操作,Personal info则在正上方横排显示,排版整体为竖版; 3、跳转后点击右侧铅笔图标;(不建议点击下方的增加语言,直接修改默认语言即可。如果要增加,也等到先把语言调整到中文后再说,方便后续其他操作) 4、在弹出的的对话框中输入“中文”,搜索,点击简体中文或繁体中文,然后点击右下角的Select; 5、界面已经修改完毕,这时候记住千万不要点击语言左侧的向左箭头(否则语言又会调回到原来的设置),直接点击左上角的Google账号图标,默认语言即修改完毕。 本文所展示的截图以英文为例,如果默认语言显示为其他国家文字,则按照图中所示位置点击即可修改成功。手机上的操作完全一致,只是位置由于界面缩放的原因,略有偏差,但基本的逻辑来讲都在正常的位置。参考本文截图同样可以在手机上操作修改谷歌账号的默认语言。 正式开始: 1、建立应用程序 2、商店设定:类型选“街机”;邮件地址填写账号的邮箱。 3、主要商店资讯:填写描述-上传ICON-主题图片- 截图等 4、应用程序内容:设置完所有声明 4.1 隐私政策地址,制作完隐私政策后将链接填入。 隐私政策制作链接:App Privacy Policy Generator 4.1-1隐私政策制作: App Name-填写应用名称 Contact Information-填写google提审账号的邮箱 Personally Identifiable Information-默认不填 App Type-选择Free Mobile OS-选择Android OwnerType-可直接默认不选,或者根据提审账号的类型选择,然后填入开发者名称 点击 下一步 勾选Google Play Services/ADMob/Google Analytics for Firebase/Facebook 这4个 点击 下一步 点击Privacy Policy→Deploy to Flycricket 填入提审的google账号和密码,进行人机认证后发布获得隐私政策链接 4.2 广告----應用程式是否包含廣告 选“是,我的應用程式包含廣告” 4.3 应用程式存取权 --- 选“我的應用程式沒有任何存取限制,所有功能可直接使用” 4.4 内容分级 --- 填入账号的邮箱地址,选“游戏”,问卷全部选“否”

数据结构二叉树——堆

前言:哈喽小伙伴们,紧随上篇文章树的讲解,我们这篇文章开始进行二叉树的讲解。 先来看二叉树的一种特殊形式——堆。 目录 一.什么是堆 二.堆的概念 三.堆的实现 1.堆的创建 2.堆的销毁 3.堆顶数据 4.堆的判空 5.堆的数据个数 6.堆的插入 7.堆的删除 8.测试 四.完整代码展示 1.Heap.h 2.Heap.c 五.总结 一.什么是堆 我们已经了解到,二叉树有顺序存储和链式存储两种方式。其中顺序存储比较特殊,它用数组来作为架构,这就要求树的各个节点之间必须是连续且有序,这样一来只有完全二叉树才符合条件,所以我们将顺序存储的二叉树另起一个新名字——堆。 二.堆的概念 堆既然作为从二叉树独立出来的一个新的数据结构,自然要有它自己的特性: 堆中的某个节点的值总是不大于或不小于其父节点的值。堆总是一棵完全二叉树。堆按照从上到下,从左到右的顺序依次在数组中排列。 如何理解第一个特性呢???来看下图: 如果一个父节点的值比它的子节点的值都小,那么我们将这样的堆称为小堆;如果一个父节点的值比它的子节点的值都大,那么我们将这样的堆称为大堆; 三.堆的实现 我现在随便给出一个数组: arr[] = { 9,4,6,2,7,1,8,4,8,2 }; 该数组可以是一棵二叉树,但是不满足堆的条件,下面我们就来创建一个堆,并将该数组的数据按照堆的规则将它们入堆。(以小堆为例) 1.堆的创建 因为是数组型数据结构,所以一开始肯定还是要创建一个堆结构体: typedef int HPDataType; typedef struct Heap { HPDataType* data; int size; int capacity; }Heap; 紧接着进行初始化: // 堆的构建 void HeapCreate(Heap* hp) { assert(hp); hp->capacity = 0; hp->size = 0; hp->data = NULL; } 2.堆的销毁 销毁也是同样的操作:

让vs2022支持wsl(linux)本地调试.net工程

win10、win11都自带wsl子系统,vs可以利用它进行linux单步调试。但有不知道哪里环境有问题,运行wsl调试时,总会报错,为了能够成功调试,我们可以自己安装一个wsl环境。 wsl 安装 管理员运行cmd,运行以下命令,安装wsl的Ubuntu系统。 wsl --install -d Ubuntu 安装时会提示输入用户名,不用管它,直接关闭,下次打开wsl,会以无密码的root用户打开 安装完毕后,重新打开cmd,输入wsl就会进入刚刚安装的系统。 如果你要卸载某个wsl子系统,可以命令: wsl --unregister Ubuntu 安装vs调试器 下载vsdbg: https://vsdebugger.azureedge.net/vsdbg-17-7-10808-2/vsdbg-linux-x64.tar.gz 下载: https://aka.ms/getvsdbgsh 都下载到 d:\Download,然后运行cmd,输入wsl进入Ubuntu子系统 输入命令安装vs调试器: cd /mnt/d/Download ./GetVsDbg.sh -v latest -l /root/vsdbg -e vsdbg-linux-x64.tar.gz 现在,你用vs2022进行wsl调试,它会提示你wsl子系统没有安装.net环境,根据它的提示,安装.net环境后,就可以正常进行wsl调试了。

【Linux基础】Linux常见指令总结及周边小知识

前言 Linux系统编程的学习我们将要开始了,学习它我们不得不谈谈它的版本发布是怎样的,谈它的版本发布就不得不说说unix。下面是unix发展史是我在百度百科了解的 Unix发展史 UNIX系统是一个分时系统。最早的UNIX系统于1970年问世。此前,只有面向批处理作业的操作系统,这样的系统对于需要立即得到响应的用户来说是太慢了。在60年代末,Kenneth Thompson和Dennis Ritchie都曾参加过交互方式分时系统Multics的设计,而开发该系统所使用的工具是CTSS。这两个系统在操作系统的发展过程中都产生过重大影响。在此基础上,在对当时现有的技术进行精选提炼和发展的过程中,K.Thompson于1969年在小型计算机上开发UNIX系统,后于1970年投入运行。 1972年,DennisRitchie开发出C语言,用来改写原来用汇编语言编写的UNIX,由此产生了UNIX VersionV。1974年,Kenneth Thompson和Dennis Ritchie合写的“The UNIX Time-Sharing System”在Communication of ACM上发表,正式向外界披露了UNIX系统。 当时,PDP-11系列小型计算机在世界各地已经得到广泛应用,UNIX系统一开发后便广泛配备于美国各大学的PDP-11系列计算机上,由此为UNIX的广泛应用创造了物质条件。 1978年,UNIX Version VI发表,随后又于1979年用于VAX-11超级小型机。以后,不断地出现各种新的版本。美国电话电报公司分别于1981年和1983年发表AT&T UNIX SystemII和UNIX SystemV。美国加州大学伯克莱分校也先后发表了UNIX的版本BSD4.1,BSD4.2和BSD4.3。 UNIX系统的用户日益增多,应用范围也日益扩大。无论在各种类型的微型机、小型机,还是在中、大型计算机,以及在计算机工作站甚至个人计算机上,很多都已配有UNIX系统。不仅新推出的机型配有UNIX系统,而且一些历史较久的生产厂商,也竞相将原有机型配上UNIX系统以便打开销路、争取市场。 2020年,苹果发布操作系统升级版本,将UNIX操作系统的强大功能和苹果电脑的易用性相结合,提高了电脑的运行速度和电池寿命。 Linux发展史 1991年10月5日,赫尔辛基大学的一名研究生Linus Benedict Torvalds在一个Usenet新闻组(comp.os.minix)中宣布他编制出了一种类似UNIX的小操作系统,叫Linux。新的操作系统是受到另一个UNIX的小操作系统——Minix的启发,该系统是由一名叫Andrew S Tanenbaum的教师开发的。读者也许猜想所发布的这个系统应该是Linux的0.01版本,实际上不是这样。真正的Linux 0.01版本并没有被发布,原因是0.01版本不实用。 Linus仅仅在第一个Linux的FTP站点(ftp://nic.funet.fi)上提供过这个版本的的源代码。Torvalds于10月5日发布的这个Linux版本被称为0.02版,它能够运行GNU Bourne Again Shell(bash)和GNU的C编译程序(gcc)以及为数不多的其它语言。 Torvalds绝对没有想到他设想的一种能够针对高级业余爱好者和黑客们的操作系统已经产生,这就是人们所称的Linux。Linux发布时的版本是0.02,后来又有0.03版,然后又跳到0.10版。因为世界各地越来越多的程序员都开始开发Linux,它已经达到0.95版。这就意味着正是公布1.0版本的时间已经为期不远了。正式的1.0版本是在1994年公布的 开源 Linux是一种自由和开放源代码的类UNIX操作系统,该操作系统的内核由林纳斯托瓦兹在1991年首次发布,之后,在加上用户空间的应用程序之后,就成为了Linux操作系统。严格来讲, Linux只是操作系统内核本身,但通常采用“Linux内核”来表达该意思。而Linux则常用来指基于Linux内核的完整操作系统,它包括GUI组件和许多其他实用工具。GNU通用公共许可协议(GNU General Public License,简称GNU GPL或GPL),是一个广泛被使用的自由软件许可协议条款,最初由理查德斯托曼为GNU计划而撰写, GPL给予了计算机程序自由软件的定义, 任何基于GPL软件开发衍生的产品在发布时必须采用GPL许可证方式,且必须公开源代码。 Linux是自由软件和开放源代码软件发展中最著名的例子。只要遵循GNU通用公共许可证,任何个人和机构都可以自由地使用Linux的所有底层源代码,也可以自由地修改和再发布。随着Linux操作系统飞速发展,各种集成在Linux上的开源软件和实用工具也得到了应用和普及,因此, Linux也成为了开源软件的代名词。 正是因为Linux是开源的,所以Linux具有很多优秀的特性。 在往后谈就要讲到Unix版本与Linux版本发布是如何一步一步到今天的了,这里就由小伙伴自己去百度搜索吧,博主就不多赘述了,下面开始我们的正题,这篇文章最主要的还是要讲解我们的指令部分。 使用XShell远程登录Linux 关于Linux桌面 很多同学的 Linux 启动进入图形化的桌面. 这个东西大家以后就可以忘记了. 以后的工作中 没有机会 使用图形界面. 思考:为什么不使用图形界面? Linux系统之所以被认为是相对安全的,是因为它具有很多安全特性和机制,如强大的权限管理、可定制的安全策略、加密文件系统等。这些安全特性和机制是Linux系统内在的设计和实现,与其图形界面的设计无关。Linux系统在设计上注重的是灵活性、稳定性和可靠性,而不是界面的友好度。因此,它通常采用了一些轻量级的桌面环境,如GNOME、KDE、XFCE等,这些桌面环境相对Windows的图形界面来说可能看起来较为简单,但是它们可以很好地适应不同的需求和使用场景。另外,Linux系统的开发和使用者通常更加倾向于使用命令行界面。命令行界面提供了更加灵活的操作方式,可以更好地控制和管理系统,也更适合一些需要自动化操作和批处理的应用场景。同时,命令行界面也可以更方便地远程管理Linux系统,这在一些需要远程管理的场景下非常重要。Linux系统之所以没有像Windows一样的图形界面,是因为它的设计目标和使用场景不同。Linux系统更注重灵活性和可定制性,同时也更加注重安全和稳定性,而不是图形界面的友好度。 下载安装XShell 我们要登陆Linux的机器就必须需要一个远程终端程序 这个我们就可以使用XShell进行登陆 安装链接献上:XShell安装 注意安装时选择“home/shool”为免费版本 安装好后打开Xshell,如下图即为安装成功了(这里可能有些兄弟可能会安装的XShell7的一些版本,可能会出现打不开的情况,情况第二张图) 解决办法,所以你可以看到我下载的是XShell5的老版本,这可能是我们电脑的问题,我目前也不理解是什么原因,有想要老版本的可以私聊博主获取哦。 使用XShell登陆主机 安装好了并打开成功,那么我们就可以进行登陆了,当然,登陆之前我们需要准备一个远程的云服务器,我们可以去阿里云、华为云等等官网去购买服务器,然后通过XShell去登陆。价钱不贵,一些时候还有活动折扣哦~~

竞赛选题 题目:基于LSTM的预测算法 - 股票预测 天气预测 房价预测

文章目录 0 简介1 基于 Keras 用 LSTM 网络做时间序列预测2 长短记忆网络3 LSTM 网络结构和原理3.1 LSTM核心思想3.2 遗忘门3.3 输入门3.4 输出门 4 基于LSTM的天气预测4.1 数据集4.2 预测示例 5 基于LSTM的股票价格预测5.1 数据集5.2 实现代码 6 lstm 预测航空旅客数目数据集预测代码 7 最后 0 简介 🔥 优质竞赛项目系列,今天要分享的是 基于LSTM的预测算法 - 股票预测 天气预测 房价预测 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/postgraduate 1 基于 Keras 用 LSTM 网络做时间序列预测 时间序列预测是一类比较困难的预测问题。 与常见的回归预测模型不同,输入变量之间的“序列依赖性”为时间序列问题增加了复杂度。 一种能够专门用来处理序列依赖性的神经网络被称为 递归神经网络(Recurrent Neural Networks、RNN)。因其训练时的出色性能,长短记忆网络(Long Short-Term Memory Network,LSTM)是深度学习中广泛使用的一种递归神经网络(RNN)。 在本篇文章中,将介绍如何在 R 中使用 keras 深度学习包构建 LSTM 神经网络模型实现时间序列预测。 如何为基于回归、窗口法和时间步的时间序列预测问题建立对应的 LSTM 网络。对于非常长的序列,如何在构建 LSTM 网络和用 LSTM 网络做预测时保持网络关于序列的状态(记忆)。 2 长短记忆网络 长短记忆网络,或 LSTM 网络,是一种递归神经网络(RNN),通过训练时在“时间上的反向传播”来克服梯度消失问题。

访问者模式 (Visitor Pattern)

定义 访问者模式(Visitor Pattern)是一种行为型设计模式,用于将算法与其作用于的对象结构分离。这种模式主要用于执行操作或应用过程,这些操作需要在不同类型的对象上执行,同时避免让这些对象的类变得过于复杂。 关键组成部分 访问者(Visitor): 一个接口或抽象类,定义了对不同类型元素(Element)的访问操作。实现了每种类型元素的操作,是将操作逻辑从元素类中分离出来的关键所在。 元素(Element): 定义了一个接受访问者的方法(通常为 accept),该方法允许访问者对象访问元素。元素结构通常稳定,且含有多个接受访问的方法,每个方法对应一种类型的访问者。 具体元素(Concrete Element): 实现元素接口,定义了 accept 方法的具体实现。可能有多个不同类型的具体元素类,每个类都有自己的逻辑和接受访问者的方式。 具体访问者(Concrete Visitor): 实现访问者接口,定义了对每个元素类的具体操作。可能有多个不同类型的具体访问者,每个访问者都实现了一套作用于元素的操作。 解决的问题 操作与对象结构的分离:在复杂对象结构中,经常需要执行各种不依赖于特定对象的操作。访问者模式使得可以将这些操作从对象结构中分离出来,以减少这些操作对于对象结构的影响。添加新操作的灵活性:当新的操作需要在这些对象上执行时,你可能不希望更改这些对象的类。访问者模式允许你通过添加新的访问者类来添加新的操作,而无需修改对象的类。集中相关操作:在传统的面向对象设计中,相关的操作可能分散在各个类中。访问者模式允许你将相关操作集中在一个访问者类中,这样可以避免在对象结构中散布这些操作,从而提高代码的组织性和可维护性。扩展性:对于那些可能需要添加新操作的对象结构,访问者模式提供了一种容易扩展的方式。你可以在不更改现有代码的情况下,通过创建新的访问者来添加新的操作。聚合操作:在一些情况下,你可能需要对一个复杂的对象结构执行聚合操作,如遍历、搜索或生成报告。访问者模式使得这些操作可以被集中管理和维护。 使用场景 复杂对象结构:在复杂的对象结构中(如树状或图状结构),需要对结构中的各个对象执行操作,而这些操作依赖于对象的具体类型。访问者模式允许在不修改这些对象类的情况下,添加新的操作。添加新操作:当需要对一个对象结构添加新的操作,且不希望这些操作影响到对象的类时。访问者模式允许将操作逻辑封装在访问者中,易于扩展。避免"污染"对象类:如果在每个对象类中添加新操作会导致类变得复杂或不易维护,那么使用访问者模式将这些操作外部化是一个好选择。不同的访问者实现不同的操作:当同一个对象结构需要支持多种不同的操作,且这些操作是互相独立的。例如,可能有一个用于渲染对象的访问者,另一个用于检查对象的完整性。频繁变更的操作:如果一组操作经常变更,但对象结构相对稳定,那么将这些操作作为访问者的一部分,可以避免频繁修改对象结构。累积状态:在遍历一个复杂结构时,如果需要在访问者中累积状态,而不是在元素中累积,那么访问者模式也是一个不错的选择。 示例代码1-计算机部件访问者 在这个例子中,我们定义了一个计算机部件(ComputerPart)的接口和一些具体部件类(Keyboard、Monitor、Mouse),以及一个访问者接口(ComputerPartVisitor)和一个具体的访问者实现(ComputerPartDisplayVisitor)。 // 访问者接口 interface ComputerPartVisitor { void visit(Computer computer); void visit(Mouse mouse); void visit(Keyboard keyboard); void visit(Monitor monitor); } // 元素接口 interface ComputerPart { void accept(ComputerPartVisitor computerPartVisitor); } // 元素实现 class Keyboard implements ComputerPart { public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } } class Monitor implements ComputerPart { public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.

模板方法模式 (Template Method Pattern)

定义 模板方法模式(Template Method Pattern)是一种行为型设计模式,它在一个方法中定义一个算法的骨架,将一些步骤的实现延迟到子类。通过这种方式,模板方法允许子类在不改变算法结构的情况下,重新定义算法的某些特定步骤。 模板方法模式通常包含以下两个角色: 抽象类(Abstract Class):定义模板方法,以及算法的骨架。它可以包含具体方法、抽象方法和钩子(hook)方法。具体子类(Concrete Class):实现抽象类中定义的抽象方法和钩子方法,从而完成算法中特定子部分的实现。 解决的问题 重复代码:在多个类中出现重复的代码是常见的问题,尤其是当这些类执行相似的任务时。模板方法模式通过将这些公共代码移到一个共同的父类中来减少重复。算法骨架的一致性:在某些情况下,你可能希望确保一个算法的基本结构保持一致,同时允许算法的某些步骤在不同的情境下有所不同。模板方法模式允许在保持算法结构不变的同时,让子类提供这些步骤的具体实现。扩展性:在不改变算法结构的情况下扩展功能。模板方法模式使得可以在子类中实现或重写某些步骤,而不需要更改基本算法的结构。反向控制结构(Inversion of Control):模板方法模式是一种反向控制结构,因为在这种模式中,高层模块(抽象类)控制算法的流程,底层模块(具体实现)则提供某些步骤的具体实现。这有助于解耦算法的定义和实现。提供算法的框架:当你想提供一个算法的框架让其他开发者使用时,模板方法模式是一个不错的选择。开发者可以根据自己的需求覆写预定义的步骤,而无需更改算法的核心流程。 使用场景 算法步骤的共性和差异性分离: 当多个类有共同的行为,且这些行为中的步骤大体上相似,但每个步骤的具体实现不同时,模板方法模式非常有用。它允许你将共同的操作抽象到一个共有的父类中,而将各个步骤的具体实现留给子类。 一次性实现算法的不变部分: 在需要实现一个算法,并且算法的大体框架是稳定的,但某些关键步骤可能会发生变化的情况下,使用模板方法模式可以固定算法的框架,并将变化的部分留给子类来实现。 扩展类的功能: 当需要扩展类功能而不改变其主体结构时,模板方法模式提供了一种机制,允许在不改变类的主体结构的前提下对其进行扩展。 避免代码重复: 在多个类中执行相似的操作时,模板方法模式可以帮助避免重复代码。通过在父类中编写通用代码,可以减少重复,并使维护变得更容易。 控制子类扩展: 当你需要控制子类的扩展点时,模板方法模式是一个很好的选择。父类可以定义哪些操作是可变的,哪些是固定的,从而提供了一种方式来防止子类改变算法的结构。 示例代码 // 抽象类定义模板方法和抽象步骤 abstract class DataParser { // 模板方法 public final void parseData() { readData(); processData(); writeData(); } // 具体方法 public void readData() { System.out.println("Reading data..."); } // 抽象方法 abstract protected void processData(); // 具体方法 public void writeData() { System.out.println("Writing data..."); } } // 具体实现类 - XML解析 class XMLDataParser extends DataParser { @Override protected void processData() { System.

策略模式 (Strategy Pattern)

定义 策略模式(Strategy Pattern)是一种行为型设计模式,它定义了算法家族,分别封装起来,让它们之间可以互相替换。策略模式使得算法的变化独立于使用算法的客户。这种模式涉及到三个角色: 上下文(Context):用来维护对某个策略对象的引用。策略接口(Strategy):定义了一个公共接口,各种不同的算法以不同的方式实现这个接口。具体策略(Concrete Strategy):实现策略接口的具体算法。 解决的问题 算法的选择与实现分离: 在许多情况下,特定任务可以有多种算法或策略。策略模式允许将算法的选择与其实现分离开来,从而使算法可以独立于使用它们的客户端代码变化。 动态替换算法: 在运行时根据不同情况或上下文动态选择最适合的算法。策略模式提供了一种机制,使得可以在运行时更改对象的行为或算法。 消除条件语句: 在传统的编程实践中,多种算法或行为常常通过条件语句(如 if-else 或 switch-case)来实现。策略模式通过将每种算法封装在独立的类中,帮助减少条件语句的使用,使代码更易于维护和理解。 扩展性: 新增算法或改变现有算法时,策略模式使得这些变更变得更容易,因为它避免了对现有代码的修改。只需添加新的策略类即可扩展新的行为。 封装算法族: 当一个应用程序需要一组算法,并且希望在不同的情况下应用不同的算法时,策略模式允许将这些算法封装在一个个独立的策略类中,并在运行时选择使用哪一个 使用场景 多种算法或行为可供选择: 当有多种相关的类仅在行为上有所差异时,策略模式允许根据具体情况选择适当的行为。 运行时选择算法: 如果在运行时需要动态地选择算法,策略模式提供了一种灵活的方式来实现这一点,使得可以根据上下文条件或输入选择最合适的算法。 避免写大量的条件判断语句: 在不使用策略模式的情况下,实现多种算法或行为常常需要使用复杂的条件判断语句(如if-else或switch-case)。策略模式通过封装算法来简化这些判断逻辑。 算法的封装和隔离: 当需要封装涉及复杂逻辑或数据的算法,并且希望将算法的实现细节隔离开来时,策略模式是一个理想的选择。 需要易于扩展和修改的算法族: 如果预计在未来需要新增或更改算法,策略模式使得扩展成为可能,且不会影响到使用算法的客户端代码。 示例代码 // 策略接口 interface Strategy { public int doOperation(int num1, int num2); } // 具体策略 class OperationAdd implements Strategy{ public int doOperation(int num1, int num2) { return num1 + num2; } } class OperationSubtract implements Strategy{ public int doOperation(int num1, int num2) { return num1 - num2; } } class OperationMultiply implements Strategy{ public int doOperation(int num1, int num2) { return num1 * num2; } } // 上下文 class Context { private Strategy strategy; public Context(Strategy strategy){ this.

嵌入式FPGA IP正在发现更广阔的用武之地

作者:郭道正, Achronix Semiconductor中国区总经理 在日前落幕的“中国集成电路设计业2023年会暨广州集成电路产业创新发展高峰论坛(ICCAD 2023)”上,Achronix的Speedcore™嵌入式FPGA硅知识产权(eFPGA IP)受到了广泛关注,预约会议、专程前往或者驻足询问的芯片设计业人士的数量超过了往届,表明了越来越多的国内开发者正在考虑为其ASIC或SoC设计添加高性能eFPGA逻辑阵列。 众多潜在用户的需求,反映了当前各行各业都在加速导入智能化技术,并利用eFPGA来在其ASIC或SoC中添加硬件数据处理加速功能,并为不断演进的算法或者标准保留可编程性。Speedcore eFPGA IP包括了查找表、存储器、数字信号处理器(DSP)和机器学习处理器(MLP)等构建模块。它们都采用了模组化的结构设计,以支持客户根据其客制化终端系统的需求,来量身定制相应的资源组合。 Achronix的Speedcore IP以GDSII格式提供,同时提供相应的文档,以支持设计师将Speedcore eFPGA实例集成到其特有的ASIC之中。Achronix还提供配套的ACE设计工具,用于编译针对Speedcore eFPGA的设计。目前,Speedcore eFPGA IP已被全球数十家领先的科技企业采用,总的出货量超过了1500万。 简要功能介绍 由于Speedcore eFPGA是一款嵌入式IP,因此它被设计为整个ASIC的一个单元组件,被ASIC的其他完全定制的单元模组所包围(见下图)。Speedcore eFPGA包括以下功能: ·可编程内核逻辑阵列,具有客户自定义的功能 ·内核I/O环 ·FPGA配置单元(FCU) ·配置存储器(CMEM) ·用于调试和编程的接口 ·用于测试的接口(DFT) 核心资源介绍 通过选择下列每种资源的数量,就可以定义一个定制Speedcore eFPGA IP的功能: ·逻辑 - 6输入查找表(LUT),加上集成的快速加法器 ·逻辑RAM - 两种选择: ·用于LRAM2k的每个存储器单元的容量最多可达2Kb,其中包括与MLP紧耦合的存储器 ·用于LRAM4k的每个存储器单元的容量最多可达4Kb ·Block RAM - 两种选择: ·用于BRAM20k的每个存储器单元的容量最多可达20Kb ·用于BRAM72k的每个存储器单元的容量最多可达72Kb,包括与MLP紧耦合的存储器 ·DSP64 - 每个单元模块有一个18 x 27乘法器、64位累加器和27位预加法器 ·MLP - 机器学习处理器(MLP)模块,包含乘法器、加法器、累加器和紧耦合存储器(包括BRAM72k和LRAM2k) 交付与应用价值 由于Achronix采用了根据客户需求来定制GDSII的商业模式,每个Speedcore eFPGA实例的资源模块的数量和组合都是基于客户需求来搭配提供。Achronix的Speedcore eFPGA IP可用于台积电(TSMC)的16FF+、16FFC、12FFC、7nm、5nm和3nm工艺技术节点,也可以移植到其他工艺节点上。 在ASIC或者SoC中嵌入Speedcore eFPGA将带来诸多好处,与一款独立的FPGA芯片相比,Speedcore eFPGA IP提供了以下优点: ·降低功耗多达75% ·节省90%的成本 ·延迟缩短到1/100,同时带宽提高了10倍。 因此,Speedcore eFPGA具有极高的应用价值。 开发与编程 Achronix是唯一一家可以同时大批量生产并交付eFPGA IP和独立FPGA芯片的公司,而且它们都采用同一套ACE开发工具来支持。设计人员可以100%确信Speedcore eFPGA IP将会正常工作,因为它在Achronix的Speedster系列独立FPGA 芯片中已得到了全面的验证,并且经过了大量的流片验证。

post请求参数全大写后台接不到参数

post请求参数全大写后台接不到参数 开发过程中,我们一般都习惯用驼峰命名法,但是特殊情况要求请求参数全大写(或者首字母大写),测试验证的时候发现,接收不到请求参数。 前端请求传递: 服务端接收不到 @Data public class SyncDto implements Serializable { /** * 项目ID */ //错误1:使用@JsonProperty("PJID") 发现就可以正常入参请求了 //错误2:请求是数值类型,所有需String改成Integer private String PJID; } springMVC使用的是Jackson来解析json格式的请求报文, 所以可以使用@JsonProperty注解来实现强制要求接受字段,如: @JsonProperty("PJID") private Integer PJID; 这样就可以接收到了

VM虚拟机系统安装Windows server 16的过程

1.新建虚拟机 选择 Windows server 16 选择自己知道的地址 保存好 点击开启虚拟机右击,点击CD/DVD点击镜像,在电脑里面找到Windows 16的镜像链接。 点击下一步 进行安装 点击自定义开始下载 虚拟机下载好之后,右击2016之后选择安装VMware Tools(T)然后进行破解。 在左下角点击文件夹,打开DVD下载软件 打开自己真机的电脑 点击D盘,随后选中云计算 随后右击属性,点击 共享 点击everyone 添加然后确定就此在真机共享完成。 选中录屏 右击属性,点击共享,选择everyone 点击添加。然后选择共享。 打开虚拟机,选择W+R 输入\\真机ip地址 点击网络 找到录屏 在自己真机中“我的电脑” 右击属性,找到真机的主机名 再打开虚拟机 W+R 输入\\主机名点击确定 输入用户名+密码 然后在网络里面找到录屏 

线程信息分析,生产环境问题

现象: 应用服务器启动不了 产生原因: 最近升级了,将单线程查询数据变成了多线程查询数据。 分析: 推测一、sql 查询时间太慢导致 排查sql 后发现,不是这个原因 取回线程启动过程的线程信息 发现线程死锁了,造成死锁的方法是这个 进一步排查,发现是并行查询的时候 获取单例方法不支持多线程 解决办法: 由于红框部分的代码会被重复调用 ,直接重写这个JdbcWrapper 类,不再调用 红框部分的数据。

Error: loaded state dict contains a parameter group that doesn’t match the size of optimizer’s group

ValueError: loaded state dict contains a parameter group that doesn't match the size of optimizer's group 错误日志: Traceback (most recent call last): File "train.py", line 128, in <module> optimizer.load_state_dict(checkpoint['optimizer_state_dict']) File "/usr/local/lib/python3.6/dist-packages/torch/optim/optimizer.py", line 115, in load_state_dict raise ValueError("loaded state dict contains a parameter group " ValueError: loaded state dict contains a parameter group that doesn't match the size of optimizer's group 这个错误通常是由于加载的模型权重和当前模型的结构不一致导致的。解决方法通常有以下几种: 确认模型结构是否一致,如果不一致需要手动修改代码或者将加载的权重进行转换。确认优化器的参数组是否和模型参数一致,如果不一致需要手动调整优化器代码或者将加载的权重进行转换。确认加载的权重是否是正确的,可以将加载的权重打印出来,与当前模型的权重进行对比。可能是 optimizer 的 state_dict 和加载的 checkpoint 的 state_dict 尺寸不匹配导致的。 以下是一个代码示例,可以帮助你更好地理解如何解决该错误:

JVM 内存分析工具 MAT及实践

线程分析工具 MAT 官网下载地址:http://www.eclipse.org/mat/downloads.php mat百度网盘链接:(速度更快) 链接:https://pan.baidu.com/s/1tMp8MQIXuPtg9zBgruO0Ug?pwd=jqtv 提取码:jqtv jdk17 百度网盘链接:https://pan.baidu.com/s/1pT2aUR9CyajNnSi006zEQw?pwd=lia3 提取码:lia3 Mat MAT(Memory Analyzer Tool)是一款用于Java应用程序内存分析的工具,它是基于Eclipse平台的插件。MAT主要用于分析Java堆转储(heap dumps)文件,这些文件通常是通过Java虚拟机(JVM)的"-XX:+HeapDumpOnOutOfMemoryError"选项或通过JVisualVM等工具生成的。 MAT提供了一些功能强大的工具,帮助开发人员诊断和解决Java应用程序中的内存问题。以下是MAT的一些主要功能: Heap Dump分析: MAT能够加载和分析Java堆转储文件,以显示应用程序中对象的内存使用情况。这包括对象的数量、类型、大小等信息。 内存泄漏检测: MAT可以帮助识别应用程序中的内存泄漏问题。它提供了一些工具,例如“Leak Suspects”报告,帮助找出潜在的内存泄漏。 GC Roots分析: MAT能够识别和显示对象的垃圾收集根(GC Roots)。通过分析GC Roots,可以了解哪些对象阻止了垃圾收集器回收内存。 对象查询和比较: MAT允许查询和比较堆转储文件中的对象。这对于查找特定类型的对象或了解对象之间的关系非常有用。 统计信息和报告: MAT生成各种统计信息和报告,更好地了解应用程序的内存使用情况。这些报告可以包括类加载信息、线程信息等。 要使用MAT,需要首先生成Java堆转储文件,然后将该文件导入MAT进行分析。MAT提供了一些图形化界面和交互式工具,使内存分析变得更加直观和易用。 MAT是一个功能强大的工具 mat 安装 拿到百度网盘文件后,解压后 MAT指定jdk环境 正常运行成功: 运行 MemoryAnalyzer.exe 选择dump 文件

element ui 上传组件实现手动上传

首先需要给上传组件增加http-request属性,这个方法中可以获取到文件,并按照自己的方式进行上传。 <el-upload ref='fileUpload' action='#' :http-request='httpRequest' :on-preview="handlePreview" :on-remove="handleRemove" :limit="1" :on-exceed="handleExceed" :file-list="fileList" :on-success='handleSuccess' accept='.xls' > <el-button size="small" type="primary" >上传文件</el-button> <div slot="tip">支持扩展名:.xls</div> </el-upload> 设置了http-request属性之后,在选取文件后马上就会调用该方法。如果不想要马上上传的话,只需要增加:auto-upload=‘false’,然后在需要上传时,调用实例的submit方法即可执行httpRequest方法 methods:{ upload(){ this.$refs.fileUpload.submit() } } 如果是单纯的上传文件,但需要携带参数的话,只需要增加属性即可,例如: <el-upload ref='fileUpload' :data="{productId:123}" action='#' :http-request='httpRequest' :on-preview="handlePreview" :on-remove="handleRemove" :limit="1" :on-exceed="handleExceed" :file-list="fileList" :on-success='handleSuccess' accept='.xls' > <el-button size="small" type="primary" >上传文件</el-button> <div slot="tip">支持扩展名:.xls</div> </el-upload> 但是如果是在表单中上传文件,且是直接和其他表单项数据一起上传的话,则需要手动进行上传。(不做表单校验则不需要手动进行数据传输,直接使用data属性包含额外参数即可) 如果需要做表单校验,则httpRequest只是为了获取到文件,首先不要设置auto-upload,选择文件后马上就调用httpRequest方法,在httpRequest方法中获取到文件并储存,方便后面做表单校验。 httpRequest(params) { this.form.file = params.file }, 在最终提交时,需要使用formData对象,包裹数据传输 this.$refs.form.validate((valid) => { if (valid) { const data = { file: this.form.file, secret: this.

什么是悲观锁,乐观锁?

什么是悲观锁? 悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。也就是说,共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。 特点:可以完全保证数据的独占性和正确性,因为每次请求都会先对数据进行加锁, 然后进行数据操作,最后再解锁,而加锁释放锁的过程会造成消耗,所以性能不高; 手动加悲观锁:读锁LOCK tables test_db read释放锁UNLOCK TABLES; 写锁:LOCK tables test_db WRITE释放锁UNLOCK TABLES 什么是乐观锁? 乐观锁总是假设最好的情况,认为共享资源每次被访问的时候不会出现问题,线程可以不停地执行,无需加锁也无需等待,只是在提交修改的时候去验证对应的资源(也就是数据)是否被其它线程修改了(具体方法可以使用版本号机制或 CAS 算法)。 特点:乐观锁是一种并发类型的锁,其本身不对数据进行加锁通而是通过业务实现锁的功能,不对数据进行加锁就意味着允许多个请求同时访问数据,同时也省掉了对数据加锁和解锁的过程,这种方式因为节省了悲观锁加锁的操作,所以可以一定程度的的提高操作的性能,不过在并发非常高的情况下,会导致大量的请求冲突,冲突导致大部分操作无功而返而浪费资源,所以在高并发的场景下,乐观锁的性能却反而不如悲观锁。

v-for 循环时直接使用 v-model 绑定value报错

v-for 循环时直接使用 v-model 绑定value报错 报错vue v-model directives cannot update the iteration variable ‘x’ itself 将 v-model 直接绑定到 v-for 迭代别名。这将无法修改 v-for 源数组,因为写入别名就像修改函数局部变量一样。考虑使用一个对象数组并在对象属性上使用 v-model。 原因:v-model 不可以直接修改 v-for 循环迭代时别名上的数据,但是,可以通过 index 下标来引用所需的数据,可以达到相同目的 <FormItem v-if="outputNameList.length !== 0" :label-width="40"> <CheckboxGroup v-model="formItem.exposedOutput" @on-change="configChanged('exposedOutput')"> <Checkbox v-for="(value,index) in outputNameList" :key="'outputCheckbox'+ index" :label="value"> // 原始checkbox的选项展示用span,想改为input,可以修改选项 <!--<span>{{value}}</span>--> // 直接绑定 v-for循环的value成员会报错 // <Input v-model="value"/> // 可以通过 index 下标来引用所需的数据,可以达到相同目的 <Input v-model="outputNameList[index]"/> </Checkbox> </CheckboxGroup> </FormItem>

主从复制读写分离?

主从复制和读写分离是常见的数据库架构策略,它们可以提高系统的性能和可靠性。下面是一个简单的实现方法: 主从复制: 配置主数据库:在主数据库上启用二进制日志(binary log),用于记录所有修改数据库的操作。配置从数据库:从数据库连接到主数据库,并使用主数据库的二进制日志进行复制。主从复制过程: 主数据库将修改记录到二进制日志中。从数据库连接到主数据库,并使用主数据库的二进制日志进行复制。从数据库读取二进制日志中的修改,并将其应用到自己的数据库中。 读写分离: 配置主数据库:主数据库只处理写操作(插入、更新、删除),不处理读操作。配置从数据库:从数据库用于处理读操作,可以配置负载均衡来分担读操作的负载。读写分离过程: 客户端发送写请求到主数据库。主数据库将修改记录到二进制日志中,并返回写操作的结果给客户端。从数据库连接到主数据库,并使用主数据库的二进制日志进行复制。当客户端发送读请求时,请求被路由到从数据库,从数据库返回数据给客户端。 通过这样的配置,主从复制实现了数据的一致性,而读写分离提高了系统的性能和可扩展性。需要注意的是,这只是一个简单的实现方法,实际应用中可能需要更复杂的配置和优化。

时间序列预测实战(十三)利用FNet模型实现滚动长期预测并可视化结果

论文地址->官方论文代码地址 官方代码地址->官方下载地址Github 个人修改代码地址-> 个人修改版本下载地址CSDN 一、本文介绍 本博客将介绍一种新的时间序列预测模型——FNet,它通过使用傅里叶变换代替自注意力机制,旨在解决传统Transformer模型中的效率问题。FNet模型通过简单的线性变换,包括非参数化的傅里叶变换,来“混合”输入令牌,从而实现了快速且高效的处理方式。这种创新的方法在保持了相对较高的准确性的同时,显著提高了训练速度,特别是在处理长序列数据时更显优势。本文的内容包括:FNet的工作原理,并通过一个实战案例展示如何实现基于FNet的可视化结果和滚动长期预测。 预测类型->多元预测、单元预测、长期预测。 适用对象->资源受限的环境,例如生产服务器或边缘设备 二、FNet的工作原理 1.FNet的框架原理 FNet是一种基于Transformer编码器架构的模型,通过替换自注意力子层为简单的线性变换,特别是傅里叶变换,来加速处理过程。FNet架构中的每一层由一个傅里叶混合子层和一个前馈子层组成(下图中的白色框)。傅里叶子层应用2D离散傅里叶变换(DFT)到其输入,一维DFT沿序列维度和隐藏维度。 总结:FNet相对于传统的Transformer的改进其实就一点就是将注意力机制替换为傅里叶变换,所以其精度并没有提升(我觉得反而有下降,但是论文内相等,但是从我的实验角度结果分析精度是有下降的),其这么改进的主要效果就是训练速度的加快,因为注意力机制一般都需要复杂计算,傅里叶变化的计算很简单。 2.FNet的主要优势 FNet的改进主要优势可能就是其训练速度了,这适合一些资源受限的环境,例如生产服务器或边缘设备,当我们在实际工作时候生产环境一般都不带有GPU的所以速度就很重要了,下面我来分析其训练速度的提升。 上面的这张图表展示了不同模型在掩码语言模型(MLM)任务中的准确性与训练步骤时间的关系。时间以毫秒(ms)为单位,采用对数尺度表示,可以看出随着训练时间的增加,准确性有所提升 图中展示了四种不同的模型: BERT(用蓝色圆点表示)Linear(用红色三角形表示)FNet(用黄色方块表示)FNet-Hybrid(用绿色星形表示) 从图中可以观察到以下几点: BERT模型在相对较短的训练时间内提供了高准确性,但随着时间的增加,准确性提升的速度放缓。Linear模型在初始阶段准确性较低,但随着训练时间的增加,其准确性的提升速度似乎比BERT模型要快。FNet模型的表现介于BERT和Linear模型之间,表明其在训练速度和准确性之间取得了一定的平衡。FNet-Hybrid模型与FNet相比,似乎在较长的训练时间内达到了更高的准确性,这表明在FNet中加入了一些自注意力机制可能会有所帮助。 此图的一个关键信息是,尽管BERT在开始时领先,但随着时间的推移,其他模型在准确性上逐渐接近BERT,这表明对于有限的训练时间,其他模型可能是更有效的选择。此外,考虑到时间和准确性的平衡我们本文的模型FNet和FNet-Hybrid可能更适合在资源有限的情况下使用。 三、数据集介绍 本文所用到的数据集为某公司的业务水平评估和其它参数具体的内容我就介绍了估计大家都是想用自己的数据进行训练模型,这里展示部分图片给大家提供参考-> ​ 四、参数讲解 模型涉及到的参数全部如下-> parser = argparse.ArgumentParser(description='FNet Multivariate Time Series Forecasting') # basic config parser.add_argument('--train', type=bool, default=True, help='Whether to conduct training') parser.add_argument('--rollingforecast', type=bool, default=True, help='rolling forecast True or False') parser.add_argument('--rolling_data_path', type=str, default='ETTh1-Test.csv', help='rolling data file') parser.add_argument('--show_results', type=bool, default=True, help='Whether show forecast and real results graph') parser.add_argument('--model', type=str, default='FNet',help='Model name') # data loader parser.

大表查询如何优化?

大表查询的优化方法有以下几种: 索引优化:通过建立合理高效的索引,提高查询的速度。SQL优化:组织优化SQL语句,使查询效率达到最优,在很多情况下要考虑索引的作用。水平拆表:如果表中的数据呈现出某一类特性,比如呈现时间特性,那么可以根据时间段将表拆分成多个。垂直拆表:将表按字段拆分成多个表,常用的字段放在一个表,不常用的字段或大字段放在另外一个表。 这些方法可以在处理大数据表时显著提高查询效率。

js 获取时间戳

1.Date.now() 2.Math.round(new Date()) 3.Date.parse(‘2018-6-25 17:41:21’) 4.Date.UTC(2018,6,25,17,41,21) 5.(new Date()).valueOf() 6.new Date().getTime() 7.Number(new Date()) 8.+new Date()

Unity 之 发布WebGL转微信小游戏过程详解

Unity 之 发布WebGL转微信小游戏 前言一,准备工作1.1 下载插件1.2 下载Unity1.3 安装微信开发者工具1.4 创建小程序 二,开始转换2.1 创建项目2.2 Mac适配2.3 Mac适配的一个问题2.4 打包报错 需要-x执行权限2.5 资源文件过大2.6 常见问题 三,发布游戏3.1 发布设置3.2 首次使用3.3 完美运行 前言 用 Unity WebGL 小游戏适配(转换)方案,本方案设计目的是降低 Unity 游戏转换到微信小游戏的开发成本。基于WebAssembly技术,无需更换Unity引擎与重写核心代码的情况下将原有游戏项目适配到微信小游戏。 效果展示 一,准备工作 1.1 下载插件 进入官方GitHub地址,找到安装与使用 – Unity插件, 也可直接点击下载,下载完成后是.unitypackage的包: 1.2 下载Unity 我这里用的是Unity2021.3.3f1c1版本: 下载时需要添加:WebGL Build Support 模块: 官方提示:转微信小游戏插件已验证Unity版本:2018、2019、2020、2021(请尽量使用LTS, 推荐使用2019、2021)。使用Big Sur版本Mac系统的童鞋,在使用2019.4.14之前的版本,会遇到些问题,则需另外安装 python3,并安装brotli 命令如下: python3 -m pip install brotli。 若你没有安装过,则等着进度条走完即可: 若已安装,则会显示python3的版本号: 1.3 安装微信开发者工具 点击进入,微信小游戏开发工具页,根据系统选择下载工具,然后安装到本地。 打开后大致长这个样子: 1.4 创建小程序 点击进入,小游戏注册页,每个邮箱仅能申请一个小程序,按照要求填写信息: 注册完成后,点击登录。然后完成小程序信息和小程序类目的信息补充。 小程序信息:按照你的需求填写即可 小程序类目:类目设置为"游戏",若不设置则后续使用此Appid打开时,否则开发工具会自动将你的项目转化成小程序。 最后,在后台界面往下滑,左侧找到”开发工具“ --> 获取AppID 目前的设置,已经满足测试需求了。 二,开始转换 2.

HarmonyOS从基础到实战-高性能华为在线答题元服务

最近看到美团、新浪、去哪儿多家互联网企业启动鸿蒙原生应用开发,这个HarmonyOS NEXT越来越引人关注。奈何当前不面向个人开发者开放,但是我们可以尝试下鸿蒙新的应用形态——元服务的开发。 元服务是基于HarmonyOS提供的一种面向未来的服务提供方式,有独立入口、免安装,以万能卡片等多种呈现形态,可提供一个或多个便捷、轻量化服务。在本文中,我将详细介绍元服务、ArkTS 语言开发以及 DevEco Studio 开发工具的端云一体化开发和低代码开发等方面,并且带大家亲自实战元服务开发-在线答题项目深度体验学习! 在线答题元服务主要功能: 接入AGC认证服务,以实现用户登录,展示个人账户信息,在线答题以及积分排行等功能。用户可以在应用中进行知识练习,上传自定义题目以丰富题库内容。利用华为云服务,实现用户答题展示成绩和排名,增加用户对学习的兴趣。使用云数据库存储题目,实现卡片的刷新和页面跳转等功能。 项目运行演示视频 HarmonyOS从基础到实战-高性能华为在线答题元视频演示 一.元服务核心内容 本文着重介绍元服务元服务轻量化、信息外显的特性,由基础知识学习到项目实战,逐步深入的带大家学习,最后使用元服务技术开发一套高性能,高可用性的在线答题元服务。 1.1 元服务 HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。运行在HarmonyOS的应用分为两种形态: 传统方式的需要安装的应用(即传统概念中的HarmonyOS应用,可简称应用)。提供特定功能、免安装的应用(即元服务,原名为原子化服务)。 本文则主要使用元服务形态进行介绍及其开发实战。 1.1.1元服务的呈现形态 鸿蒙万能卡片是元服务的主要展现形式之一(其他形式包括语音和图标等)。每个万能卡片都是一种始终可见的元服务或应用,将重要信息以卡片的形式展示在桌面上,通过轻量交互实现服务的便捷访问。 1.1.2 元服务的特点 ① 免安装,更轻量化地将服务带给用户 ② 一键服务直达,将用户感兴趣的内容前置、外显 ③ 跨端转移,多终端设备间无缝流转 ④ 情景智能卡片推荐,随心定制、更懂用户 1.2 ArkTS语言 ArkTS是鸿蒙生态的应用开发语言。它在保持TypeScript(简称TS)基本语法风格的基础上,对TS的动态类型特性施加更严格的约束,引入静态类型。同时,提供了声明式UI、状态管理等相应的能力,让开发者可以以更简洁、更自然的方式开发高性能应用。 1.2.1 ArkTS语言特点 ArkTS语言通过不断的迭代升级有了许多更新和改进,一年前我第一次接触这个技术,发现很多地方都不完善,相比其他语言(TS,JS)相比有很多不足。但是经过一年的迭代更新,其功能现在已经十分完善且强大。让开发者能够更高效地编写和开发应用程序。 ArkTS提供了简洁自然的声明式语法、组件化机制、数据-UI自动关联等能力,实现了贴近自然语言,书写效率更高的编程方式,为开发者带来易学、易懂、极简开发的优质体验。 在使用ArkTS语言开发应用时,状态管理是一个重要的概念。状态管理是指管理应用中的各种状态,包括组件状态、全局状态等。状态管理可以帮助开发者更好地组织和管理应用中的数据,使得应用更加稳定和高效。ArkTS提供了多维度的状态管理机制,可以在ArkUI开发框架中使用。和UI相关联的数据,不仅可以在组件内使用,还可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,也可以是应用全局范围内的传递。 1.2.2 能力扩展 ArkTS在TS的基础上主要扩展了如下能力: 基本语法:ArkTS定义了声明式UI描述、自定义组件和动态扩展UI元素的能力,再配合ArkUI开发框架中的系统组件及其相关的事件方法、属性方法等共同构成了UI开发的主体。状态管理:ArkTS提供了多维度的状态管理机制。在UI开发框架中,与UI相关联的数据可以在组件内使用,也可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递。开发者可以灵活的利用这些能力来实现数据和UI的联动。渲染控制:ArkTS提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的UI内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。数据懒加载从数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。 1.3 DevEco Studio开发工具 DevEco Studio 3.1配套支持HarmonyOS 3.1版本及以上的应用及服务开发,提供了代码智能编辑、低代码开发、双向预览等功能,以及轻量构建工具DevEco Hvigor 、本地模拟器,持续提升应用及服务开发效率。 官方下载地址:HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 1.3.1低代码开发 HarmonyOS低代码,有丰富的UI界面编辑功能,例如基于图形化的自由拖拽、数据的参数化配置等,通过可视化界面开发方式快速构建布局,可有效降低用户的时间成本和提升用户构建UI界面的效率。我们来一起体验一下: 只需在创建新项目时打开低代码按钮(Enable Super Visual)即可: 创建项目之后,我们只需拖动组件到可视化区域即可,我们需要了解下面的工作区功能如下: UI Control:UI控件栏,可以将相应的组件选中并拖动到画布(Canvas)中,实现控件的添加。Component Tree:组件树,在低代码开发界面中,开发者可以直观地看到组件的层级结构、摘要信息以及错误提示。开发者可以通过选中组件树中的组件(画布中对应的组件被同步选中),实现画布内组件的快速定位;单击组件后的或图标,可以隐藏/显示相应的组件。Panel:功能面板,包括常用的画布缩小放大、撤销、显示/隐藏组件虚拟边框、设备切换、明暗模式切换、Media query切换、可视化布局界面一键转换为hml和css文件等。Canvas:画布,开发者可在此区域对组件进行拖拽、拉伸等可视化操作,构建UI界面布局效果。Attributes & Styles:属性样式栏,选中画布中的相应组件后,在右侧属性样式栏可以对该组件的属性样式进行配置。 我们可以利用可视化来做各种各样的前端页面,这大大的降低了我们的工作量,下面则是一个可视化拖动的效果页面,具体的内容我们则可以到低代码开发文档中进行深度学习。

node.js优秀web框架

Node.js有许多优秀的Web框架,以下是一些常用的: 1. Express.js:Express是最流行的Node.js Web框架,它是一个简洁、灵活的框架,提供了一系列强大的特性,如中间件、模板引擎支持、路由等。 2. Koa.js:Koa是由Express的原团队开发的一个新的Web框架,它使用了更现代的JavaScript特性,如async/await,提供了更优雅的异步处理和更好的错误处理。 3. Hapi.js:Hapi是一个丰富的框架,提供了大量的插件和工具,适合构建大型和复杂的应用。 4. Sails.js:Sails是一个MVC框架,提供了类似Ruby on Rails的开发体验,适合构建RESTful API和实时应用。 5. Nest.js:Nest是一个全新的框架,它使用TypeScript编写,提供了一种模块化和面向对象的开发方式,适合构建大型和复杂的应用。 以上这些框架各有优点,选择哪一个取决于您的具体需求和喜好。