本文记录了ODL控制器中Notification的开发过程
1. Yang文件的编写
首先在api目录构建自己的yang文件:packetsend.yang
在yang文件里边编写notification服务
// Contents of "packetsend"
module packetsend {
namespace "urn:opendaylight:packetsend";
prefix "packetsend";
revision 2018-05-12 {
description "Initial revision";
}
notification send-packet{
leaf name{
type string;
}
leaf content{
type string;
}
}
notification news{
leaf content{
type string;
}
}
}通过notification关键字来创建notification服务
编写完成后保存会自动问我们生成binding接口
每一个notification会对应一个接口和相应的builder,这里定义了两个notification所以会有两个builder,里边的成员变量就是我们在yang文件中定义的变量,比如SendPacket和SendPacketBuilder里边会有name和content变量,然后还会生成一个PacketsendListener接口在这个接口里边定义了两个方法,分别对应了我们在yang文件中定义的两个notification,这两天方法是:
void onSendPacket(SendPacket notification);
void onNews(News notification);
接听者需要implements这个接口并实现这两个方法
2. 创建发布者
发布-订阅模式中首先需要有一个发布者,在impl下创建一个发布类Radio类,具体代码如下:
public class Radio {
NotificationPublishService publishService;// 发布需要依赖这个服务,需要在blueprint里边注入
Timer timer1 = new Timer();
systemd POST --> Boot Sequence --> Bootloader --> kernel + initramfs(initrd) --> rootfs --> /sbin/init init: CentOS 5: SysV init CentOS 6: Upstart CentOS 7: Systemd Systemd:系统启动和服务器守护进程管理器,负责在系统启动或运行时,激活系统资源,服务器进程和其它进程 Systemd新特性: 系统引导时实现服务 并行启动 按需启动守护进程 (尽可能的启动必要的服务) 自动化的服务依赖关系管理 同时采用socket式与D-Bus总线式激活服务 系统状态快照 核心概念:unit unit表示不同类型的systemd对象,通过配置文件进行标识和配置;文件中主要包含了系统服务、监听socket、保存的系统快照以及其它与init相关的信息 配置文件: /usr/lib/systemd/system:每个服务最主要的启动脚本设置,类似于之前的/etc/init.d/ 【存放了不同类型的unit单元】 /run/systemd/system:系统 执行过程中所产生的服务脚本,比上面目录优先运行 /etc/systemd/system: 管理员建立的执行脚本,类似于/etc/rc.d/rcN.d/Sxx类的功能,比上面目录优先运行 unit类型: systemctl –t help 查看unit类型 Service unit: 文件扩展名为.service, 用于定义系统服务 Target unit: 文件扩展名为.target,用于模拟实现运行级别 Device unit: .device, 用于定义内核识别的设备 Mount unit: .mount, 定义文件系统挂载点 Socket unit: .socket, 用于标识进程间通信用的socket文件,也可在系统启动时,延迟启动服务,实现按需启动 Snapshot unit: .
IIC的基本介绍 IIC的简介 IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。它是半双工通信方式。
IIC总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。IIC总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。 IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控器件产生。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。
一般情况下,数据线SDA和时钟线SCL都是处于上拉电阻状态。因为:在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。
STM32的IIC接口 目前绝大多数的MCU都附带IIC总线接口,STM32也不例外。但是在本文中,我们不使用STM32的硬件IIC来读取24C02,而是通过软件的方式来模拟。
原因是因为:STM32的硬件IIC非常复杂,更重要的是它并不稳定,故不推荐使用。
IIC协议 IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。同时我们还要介绍其空闲状态、数据的有效性、数据传输。
先来看一下IIC总线的时序图:
这可能会比较复杂,可以先看一份简化了的时序图:
空闲状态 当IIC总线的数据线SDA和时钟线SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。 起始信号与停止信号 起始信号:当时钟线SCL为高期间,数据线SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号;停止信号:当时钟线SCL为高期间,数据线SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。 应答信号 发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。 应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。 对于反馈有效应答位ACK的要求是:接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放数据线SDA,以便主控接收器发送一个停止信号P。
数据有效性 IIC总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定;只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。 即:数据在时钟线SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。
数据的传达 在IIC总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。
延时时间 IIC总线的数据传送 IIC总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址(地址通过物理接地或者拉高),主从设备之间就通过这个地址来确定与哪个器件进行通信,在通常的应用中,我们把CPU带I2C总线接口的模块作为主设备,把挂接在总线上的其他设备都作为从设备。
也就是说,主设备在传输有效数据之前要先指定从设备的地址,地址指定的过程和上面数据传输的过程一样,只不过大多数从设备的地址是7位的,然后协议规定再给地址添加一个最低位用来表示接下来数据传输的方向,0表示主设备向从设备写数据,1表示主设备向从设备读数据。
主设备往从设备中写数据。数据传输格式如下: 淡蓝色部分表示数据由主机向从机传送,粉红色部分则表示数据由从机向主机传送。
写用0来表示(高电平),读用1来表示(低电平)。
主设备从从设备中读数据。数据传输格式如下: 在从机产生响应时,主机从发送变成接收,从机从接收变成发送。之后,数据由从机发送,主机接收,每个应答由主机产生,时钟信号仍由主机产生。若主机要终止本次传输,则发送一个非应答信号,接着主机产生停止条件。
主设备往从设备中写数据,然后重启起始条件,紧接着从从设备中读取数据;或者是主设备从从设备中读数据,然后重启起始条件,紧接着主设备往从设备中写数据。数据传输格式如下: 在多主的通信系统中,总线上有多个节点,它们都有自己的寻址地址,可以作为从节点被别的节点访问,同时它们都可以作为主节点向其它的节点发送控制字节和传送数据。但是如果有两个或两个以上的节点都向总线上发送启动信号并开始传送数据,这样就形成了冲突。要解决这种冲突,就要进行仲裁的判决,这就是I2C总线上的仲裁。
I2C总线上的仲裁分两部分:SCL线的同步和SDA线的仲裁。
这部分就暂时不介绍了,想要了解:可以参考链接浅谈I2C总线或I2C总线协议图解。
IIC底层驱动程序分析 现拟采用PB6、PB7来模拟IIC时序,其中:PB6为时钟线,PB7为数据线。
首先进行一些必要的宏定义:
//IO方向设置 #define SDA_IN() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;} #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;} //IO操作函数 #define IIC_SCL PBout(6) //SCL #define IIC_SDA PBout(7) //SDA #define READ_SDA PBin(7) //输入SDA //IIC所有操作函数 void IIC_Init(void); //初始化IIC的IO口 void IIC_Start(void); //发送IIC开始信号 void IIC_Stop(void); //发送IIC停止信号 void IIC_Send_Byte(u8 txd); //IIC发送一个字节 u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节 u8 IIC_Wait_Ack(void); //IIC等待ACK信号 void IIC_Ack(void); //IIC发送ACK信号 void IIC_NAck(void); //IIC不发送ACK信号 由于IIC是半双工通信方式,因而数据线SDA可能会数据输入,也可能是数据输出,需要定义IIC_SDA来进行输出、READ_SDA来进行输入,与此同时就要对IO口进行模式配置:SDA_IN()和SDA_OUT()。
微控制器抽象层位于AUTOSAR分层模型中BSW最底层,包含内部驱动,可以直接访问微控制器和片内外设。更进一步地,MCAL又可以分为微控制器驱动、存储器驱动、通信驱动和I/O驱动四个部分,各部分又由具体的与微控制器硬件相对应的驱动模块组成。如下图所示。
1、微控制器驱动
微控制器驱动由通用定时器驱动(General Purpose Driver,GPT Driver)、看门狗驱动(Watchdog Driver,WDG Driver)、微控制器单元驱动(Microcontroller Unit Driver,MCU Driver)和内核测试(Core Test)四个部分组成。
(1)GPT Driver
在AUTOSAR中有两类定时器,操作系统定时器和硬件定时器。该模块使用通用定时器单元的硬件定时器通道,为操作系统或者其他基础软件模块提供计时功能。GPT驱动的作用是:
启动和停止硬件定时器;
得到定时器数值;
控制时间触发的中断;
控制时间触发的中断唤醒。
(2)WDG Driver
WDG Driver的功能主要是初始化和触发看门狗。WDG Driver有内部WDG Driver和外部WDG Driver。内部WDG Driver控制MCU的内部看门狗定时器,提供触发功能和模式选择服务;外部WDG Driver控制外部硬件看门狗,与内部WDG Driver一样,提供触发功能和模式选择服务。
(3)MCU Driver
MCU Driver位于MCAL层,可以直接访问微控制器硬件,它的主要功能是初始化、休眠、复位微控制器以及提供其他MCAL软件模块所需的与微控制器相关的特殊功能。MCU Driver还能够使能并设置MCU时钟,例如CPU时钟、外围器件时钟、预分频器等参数。
(4)Core Test
Core Test(内核测试)模块包含周期性测试和启动测试。内核测试模块可以对CPU所有寄存器进行测试,提供中断控制和异常检测。该模块还对算术逻辑单元、存储保护单元和缓存控制器等进行检测。
2、存储器驱动 存储器驱动由内部EEPROM驱动、内部Flash驱动、RAM测试和Flash测试四部分组成。
(1)内部EEPROM驱动
内部EEPROM驱动提供初始化服务,以及对内部EEPROM的读写、写、擦除等操作。该驱动模块一次只能接受一个任务。
(2)内部Flash驱动
内部Flash驱动提供内部Flash初始化服务,以及对内部Flash的读、写、擦除等操作。该驱动还可以将Flash访问代码下载到RAM中,如果需要的话,也可以执行写、擦除操作。
(3)RAM测试
RAM测试模块通过软件对RAM存储进行测试。该模块包含后台测试和前台测试。其中,后台测试是异步服务,前台测试是同步服务。
(4)Flash测试
flash测试模块提供算法来测试诸如数据/程序闪存、程序SRAM等非易失性存储器,这些存储器可以是集成在微控制器内部的,也可以是外部映射到微控制器的存储器。
3、通信驱动
通信驱动由以太网(Ethernet)驱动、FlexRay驱动、CAN驱动、LIN驱动和SPI驱动五部分组成。
(1)Ethernet驱动
Ethernet驱动模块为以太网提供统一的接口。该驱动模块对所使用的以太网控制器的硬件特性进行了抽象。以太网接口模块使用以太网驱动层访问某些控制器。以太网驱动层由若干个以太网驱动模块组成。如下图所示。
(2)FlexRay驱动
FlexRay驱动用来抽象不同的FlexRay通信控制器及其硬件相关的特性。通信控制器的FlexRay协议强制特性经过封装后只能通过统一的API进行访问。API提供了映射到基于实际通信控制器的硬件访问序列的抽象功能操作。因此,使用FlexRay驱动可以保证FlexRay接口独立于硬件。对内部或外部FlexRay通信控制器的驱动来说,需要进行下列处理:
FlexRay控制器的初始化;
配置数据处理单元;
控制指令向通信控制器的传递;
从协议引擎到控制器主接口状态数据的规定;
通信控制器和主处理机之间信息数据的传输。
(3)CAN驱动
CAN驱动针对的是微控制器内部的CAN控制器,它可以实现以下功能:
对CAN控制器进行初始化;
发送和接收报文;
对报文的数据和功能进行通知(对接收报文的指示、对发送报文的确认);
溢出和错误处理;
唤醒检测。
此外,CAN驱动还具有以下特性:单个或多个CAN通道、CAN驱动的多重实例化、对接收报文的中断/轮询模式。
CAN驱动是MCAL的一部分,可以执行硬件访问、向上层提供独立于硬件的API,而仅有的能够访问CAN驱动的上层是CAN接口(CAN Interface)。CAN驱动也可以为数据传输的初始化和通知接收事件的回调函数提供服务,该服务也是独立于硬件的。除此之外,CAN驱动也可以控制从属于同一个CAN硬件单元的CAN控制器的行为和状态。
首先你得下载相应的.dtd文件。一般情况下,下载的jar中都有,所以不需要额外再去下载。
比如:mybatis,但你下载了mybatis-3.2.7.jar后,这里面就有dtd文件,你可以先进行解压
然后再去搜索.dtd文件即可找到。这里给出mybatis的jar中dtd文件的路径:
解压后目录\org\apache\ibatis\builder\xml,在最后的xml文件夹中就有两个dtd文件。
mybatis-3-mapper.dtd和mybatis-3-config.dtd。
你要是想在sqlMapConfig.xml中有智能提示需要进行以下操作:
eclipse中window->preferences->xml catalog->add
public ID,则key:-//mybatis.org//DTD Config 3.0//EN
如果你选用URI,则key:http://mybatis.org/dtd/mybatis-3-config.dtd 至此。配置完毕。怎么用呢?如下:
第一种用法: new->other...
接着点击next,不要点finish。直到出现如下页面
选择好后,就点击next,再点击finish。至此结束!新建的这个xml已经具有智能提示了
效果预览:
一、准备好对应的 QSqlTableModel #ifndef LOCALMUSICMODEL_H #define LOCALMUSICMODEL_H #include <QObject> #include <QSqlTableModel> #include <QMediaPlayer> #include "libzplay.h" using namespace libZPlay; struct songInfo { QString Artist; QString title; QString album; qint32 duration = 0; QString path; }; class LocalMusicModel : public QSqlTableModel { Q_OBJECT Q_PROPERTY(int m_musicNum READ musicNum WRITE setMusicNum NOTIFY musicNumChanged) public: explicit LocalMusicModel(QObject *parent = nullptr); QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; Q_INVOKABLE void reloadMusicRecord(const QString &path); int musicNum(){return m_musicNum;} void setMusicNum(int val){ m_musicNum = val; emit musicNumChanged(); } signals: void musicNumChanged(); private: void parseMusicInfo(QString path); void clearDb(); private: ZPlay *player; int m_musicNum = 0; }; #endif // LOCALMUSICMODEL_H #include "
重启网卡 报Job for network.service failed because the control process exited with error code. See “systemctl status network.service” and “journalctl -xe” for details. 的错误
解决方法:
然后:再次重启网卡即可获得IP地址
桥接网卡获取不到地址的解决方法:
第一步:修改虚拟网络编辑器:
第二步,查看是否有ifcfg的配置文件,修改配置文件
前言 在开发项目的过程中,我深刻的意识到,文档存在的意义并不是无用的报告,简洁明了的文档不光能记录你当下所做的,还能在繁重的工作中分神思考下一步该做什么时为你节约精力,并且在项目周期内,使整个项目保持一致性。所以,软件开发文档的编写是很有必要的。我参考网上的资料,结合自己项目开发时的心得,分享一些经验。
文档类型 在项目开发过程中,应该按要求编写好十三种文档,文档编写要求具有针对性、精确性、清晰性、完整性、灵活性、可追溯性。同时依照项目人员的角色划分,完成不同类型的文档。以下排序并未严格按照时间排序。
类型说明 可行性分析报告(产品人员) 可行性研究报告的编写目的是:说明该软件开发项目的实现在技术、经济和社会条件方面的可行性;评述为了合理达到开发目标而可能选择的各种方案;实施方案的利弊;说明并论证所选定的方案。
项目开发计划(产品人员) 软件项目开发计划即为软件项目实施方案制定出的具体计划。项目开发计划应提前给管理部门,并作为开发阶段评审的基础。编写项目开发计划的目的是用文件的形式,把对于在开发过程中各项工作的负责人员、开发进度、所需经费预算、所需的软硬条件等问题做出的安排记载下来,以便根据本计划开展和检查项目的开发工作。
软件需求说明书(产品人员) 软件需求说明书也称为软件规格说明。该说明书对所开发软件的功能、性能、用户界面及运行环境等做出详细的说明。它是用户与开发人员双方对软件需求取得共同理解基础上达成的协议,也是实施开发工作的基础。软件需求说明书的编写目的就是为了使用户和软件开发者双方对该软件的初需求有一个共同的理解,并使之成为整个开发工作的基础。
概要设计说明书 (开发人员) 概要设计说明书又可称系统设计说明书,这里所说的系统是指程序系统。编写的目的是说明对程序系统的设计考虑,包括程序系统的基本处理。流程、程序系统的组织结构、模块划分、功能分配、接口设计。运行设计、数据结构设计和出错处理设计等,为程序的详细设计提供基础。
详细设计规格说明书(开发人员) 详细设计说明书又可称程序设计说明书。编写目的是说明一个软件系统各个层次中的每一个程序(每人模块或子程序)的设计考虑。如果项目比较简单,层次较少,本文件可以不单独编写,有关内容合并入概要设计说明书。
用户操作手册(产品人员) 用户操作手册的编写是要使用非专门术语的语言,充分地描述该软件系统所具有的功能及基本的使用方法,提供该软件每一个运行的具体过程和有关知识,包括操作方法的细节。使用户(或潜在用户)通过本手册能够了解该软件的用途,并且能够确定在什么情况下,如何使用它。
测试计划(测试人员) 测试计划是软件项目实施计划中的一项重要的内容,应当在软件开发初期、即需求分析阶段制订。测试计划应当定义被测试对象和测试目标,确定测试阶段和测试周期的划分;制订测试人员、软硬件资源和测试进度等方面的计划,规定软件测试方法,测试标准以及支持环境和测试工具。针对子系统在特定的测试阶段所要进行的测试工作制订详细计划,它详细说明规定了测试小组的各项测试任务,测试策略、任务分配和进度安排等。
测试分析报告(测试人员) 测试工作完成以后,应当提交测试计划情况说明书,对测试结果加以分析,并提出测试的结论性意见。
开发进度月报(开发人员) 开发进度月报的编写目的是及时向有关部门汇报项目开发的进度和情况,以便及时发现和处理开发过程中出现的问题,一般,开发进度月报是以项目组单位每月编写的。如果被开发的软件系统规模比较大,整个工程项目被划分给若干个分项目驵承担,开发进度月报将以分项目为单位每月编写。
项目开发总结报告(产品人员) 软件项目开发完成之后,应当与项目实施计划对照,总结实际执行的情况,如进度、成果、资源利用、成本和投入的人力。此外,还需对开发工作做出评价,总结经验和教训。项目开发总结报告的编写是为了总结本项目开发工作的经验,说明实际取得的开发结果以及对整个开发工作的各个方面的评价。
软件维护手册(开发人员) 主要包括软件系统说明、程序模块说明、操作环境、支持软件的说明、维护 过程的说明,便于软件的维护。
软件问题报告(测试人员) 指出软件问题的登记情况,如日期、发现人、状态、问题所属模块等,为软件修改提供准备文档。
软件修改报告(开发人员) 软件产品投入运行以后,发现了需对其进行修正、更改等问题,应将存在的问题、修改的考虑以及修改的影响作出详细的描述,提交审批。 总结 根据项目的规模大小,以及人员构成,对所需要的文档进行编写,将大大提高项目开发的效率及规范程度。
参考资料 软件开发相关文档 – 刘米雪软件开发文档总集 – Recode_的专栏软件开发文档编写规范 – zhanghui962623727的博客
微信小程序开发交流qq群 173683895
承接微信小程序开发。扫码加微信。 正文: 选择器示例demo:
1.普通选择器 2.多列选择器 3.时间选择器 4.日期选择器 5.省市区选择器
源码:
wxml
<view class="container"> <!--选择器--> <view class="section"> <view class="section__title">普通选择器:(普通数组)</view> <picker bindchange="bindPickerChange" value="{{index}}" range="{{array}}"> <view class="picker"> 当前选择:{{array[index]}} </view> </picker> </view> <!--选择器--> <view class="section"> <view class="section__title">普通选择器2:(普通json格式数组)</view> <picker bindchange="bindPickerChange2" value="{{objectIndex}}" range="{{objectArray}}" range-key="name"> <view class="picker"> 当前选择:{{objectArray[objectIndex].name}} </view> </picker> </view> <!--选择器--> <view class="section"> <view class="section__title">多列选择器:</view> <picker mode="multiSelector" bindchange="bindMultiPickerChange" bindcolumnchange="bindMultiPickerColumnChange" value="{{multiIndex}}" range="{{multiArray}}"> <view class="picker"> 当前选择:{{multiArray[0][multiIndex[0]]}},{{multiArray[1][multiIndex[1]]}} </view> </picker> </view> <!--选择器--> <view class="section"> <view class="section__title">时间选择器:</view> <picker mode="time" value="
五一假期前落下了几节操作系统的课,现在艰难的恶补中。。
以下是分页存储管理相关的一些知识点梳理。
首先我们应该知道的概念:
逻辑地址:是程序编译后,生成的目标模块进行编址时都是从0号开始编址,称之为目标模块的相对地址,即逻辑地址。
虚拟地址:计算机处理器的地址有32位和64位的两种,对应的虚拟地址的空间大小分别是2^32字节和2^64字节,字节用B表示。
页:分页存储管理将进程的逻辑地址空间划分为若干页(面),并且对其编号,号数从0开始,每个页(面)的大小称为页面大小,且大小应为2的幂。
物理块:将内存的物理地址空间划分为若干块,称为物理块,物理块与页(面)一一对应。
页表:又称页面映像表,存储在内存中,通过页表建立页(面)与物理块的索引。
下面通过举例子梳理一下:
假设我们已经知道了逻辑地址是32位,页面大小是4KB=2^12B,页表项是4B(32位)。
1.因为逻辑地址我们假设为32位,可知虚拟地址的空间大小是2^32B。
逻辑地址:在分页地址中划为两部分,一个是页号P(页面数目),另一个是位移量W(物理块号)。
2.由已知条件求得页面数目P=2^32B/2^12B=2^20页,同时得出页号地址是20位。
A表示逻辑地址空间中的地址,L表示页面大小。
3.页表项:在页表中,一个页号与其对应的物理块号称之为一个页表项(由已知条件知道大小是32位)。故页表项的数目就等于页(面)数目即为2^20个,全部页表项(页表中从上往下数)所需的地址也就是20位。
红框即为一个页表项,以此类推。
4.物理块号的地址=逻辑地址-页号地址=32-20=12位,因为并不是进程的每一个页面都要调入内存,所以只有部分页面有对应内存的物理块号,所以物理块号的大小(2^12)会小于页号大小(2^20)。
以上是我个人的理解,欢迎交流指正。
最近闲来无事云开发了个Java刷题的小程序,有兴趣的可以看看哈。——2019.09.20
█ 【安卓学习之常见问题】 Google Play问题-Android 4.4.4平板电脑不能安装 – (Your device isn’t compatible with this version) █ 问题: ● 客户反应在平板电脑(android 4.4.4)上,安装不了app
● 找了台平板电脑(android 4.4.4),安装正常,运行正常
● 客户又测试一次,还是如此:(Your device isn’t compatible with this version)
█ 解决: ● 1.核对下app的AndroidManifest.xml文件的安装限制:
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="21" /> PS:编译环境是Android 5.0,安装最低版本是Android 3.0.x,没问题
● 2.APP直接安装可以,APP从Google Play平台上面下载不了,
PS:问题是,APP和Google Play平台之间的问题,而平台上面也没有限制只能手机才可以安装!
● 3.百度 关键字 【Your device isn’t compatible with this version】
● 4.大概问题就是 Google Play平台会通过会对【AndroidManifest.xml】文件声明的硬件权限,来判断设备是否包含该硬件,从而过滤掉不能安装的设备,比如平板电脑不支持手机卡,那么就提示"Your device isn’t compatible with this version"。
● 5.将通过< uses-permission … />声明的的权限,再次通过< uses-feature … android:required=“false”/>声明一次,表示该权限不是必须的即可!具体每个权限permission对应的feature,要从【Android Developers】中去找,参考【相关资料 3 Google Play 和根据功能进行过滤】和【相关资料 4 功能参考资料】
在CentOS6上安装TensorFlow1.2后,import tensorflow时出现以下问题:
1 ImportError: /lib64/libc.so.6: version `GLIBC_2.17' not found 这个错误的原因是未安装2.17版本的glibc库。
而在CentOS上,使用yum install glibc命令,只能更新到2.12版本。需要手动下载编译安装。
glibc-2.17下载地址:https://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz
下载glibc并解压缩
1 2 wget https://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz tar -xvf glibc-2.17.tar.gz 编译安装
1 2 3 4 5 cd glibc-2.17 mkdir build cd build ../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin make && make install 查看glibc共享库:
1 ll /lib64/libc.so.6 现libc.so.6已经软链接到2.17版本
1 lrwxrwxrwx 1 root root 12 7月 21 10:11 /lib64/libc.so.6 -> libc-2.17.so 可以查看系统中可使用的glibc版本
1 strings /lib64/libc.so.6 |grep GLIBC_ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 GLIBC_2.
1、打开需要查看的项目,选择AS上方标题栏的Analyze选项;
2、选择 Run Inspection by Name
3、在弹出框内输入 unused resources
4、筛选你需要查看的资源(像第一个:完整的项目;第二个:仅app这个Module)
5、好了,这时没有引用的资源文件就学会显示在下方;
https://blog.csdn.net/mrib/article/details/77897581点击打开链接
早上查资料,偶然发现这个话题,发现自己并不会,于是乎,下来研究了一下。 想想之前我们用jquery写请求的时候,要实现请求的串行执行,我们可能是这么做的。
$.ajax({ url: '', data: '', success: function (data) { $.ajax({ url: '', data: '', success: function (data) { $.ajax({ // 如此一层嵌套一层 }) } }) } }) 回掉嵌套的这么深,看起来很痛苦啊,于是乎我们的promise出现啦,完美的解决我们的回掉地狱~
使用promise实现==串行==很简单,调用promise.all()方法就好
那如何比较优雅的实现几个操作的==串行==呐?
在promise中返回一个promise对象就是一个串行。
下面我们来简单实现一个。
下面 /** * 创建promise * @param {Number} value */ function makePromise (value) { return new Promise((resolve) => { setTimeout(() => { resolve(value); }, Math.random() * 1000) }) } /** * 打印结果 * @param {Number} value */ function print (value) { return value } let promises = [1, 3, 4, 5, 6].
一、基本安装
1.运行以下命令安装 vsftpd。
yum install -y vsftpd
2.运行以下命令打开及查看etc/vsftpd
cd /etc/vsftpd
ls
说明:
/etc/vsftpd/vsftpd.conf 是核心配置文件。
/etc/vsftpd/ftpusers 是黑名单文件,此文件里的用户不允许访问 FTP 服务器。
/etc/vsftpd/user_list 是白名单文件,是允许访问 FTP 服务器的用户列表。
/etc/vsftpd/vsftpd_conf_migrate.sh 是vsftpd操作的一些变量和设置
备注:使用命令 rpm -ql vsftpd 可列出vsftpd中包含的文件
3.运行以下命令设置开机自启动。
systemctl enable vsftpd
4.运行以下命令启动 FTP 服务。
systemctl start vsftpd
5.运行以下命令查看 FTP 服务端口。
netstat -antup | grep ftp
6.配置本地用户登录
本地用户登录就是指用户使用 Linux 操作系统中的用户账号和密码登录 FTP 服务器。
vsftpd 安装后默只支持匿名 FTP 登录,用户如果试图使用 Linux 操作系统中的账号登录服务器,将会被 vsftpd 拒绝,但可以在 vsftpd 里配置用户账号和密码登录。具体步骤如下:
a.运行以下命令创建 ftptest 用户。
useradd ftptest (删除用户命令:sudo userdel -r newuser)
HTML5可以下载的,不需要后端,纯前端支持。HTML5的一个例子:
var content = "file content!"; var data = new Blob([content],{type:"text/plain;charset=UTF-8"}); var downloadUrl = window.URL.createObjectURL(data); var anchor = document.createElement("a"); anchor.href = downloadUrl; anchor.download = "文件名.txt"; anchor.click(); window.URL.revokeObjectURL(data); //文件下载 var blob = new Blob([要保存的文件流], { type: 'application/octet-stream' }), fileName = 'filename' + path.substring(path.lastIndexOf("."), path.length); filename,摘取了常用的部分,其实还有其他一些mimetypes = array( 'doc' => 'application/msword', 'bin' => 'application/octet-stream', 'exe' => 'application/octet-stream', 'so' => 'application/octet-stream', 'dll' => 'application/octet-stream', 'pdf' => 'application/pdf', 'ai' => 'application/postscript', 'xls' => 'application/vnd.
一、path模块的引入。
直接引用。node中自带的模块
const path = require('path'); 二、path.join(path1,path2,path3.......)
作用:将路径片段使用特定的分隔符(window:\)连接起来形成路径,并规范化生成的路径。若任意一个路径片段类型错误,会报错。
const path = require('path'); let myPath = path.join(__dirname,'/img/so'); let myPath2 = path.join(__dirname,'./img/so'); let myPath3=path.join('/foo', 'bar', 'baz/asdf', 'quux', '..'); console.log(__dirname); console.log(myPath); console.log(myPath2); console.log(myPath3); 三、path.resolve([from...],to)
作用:把一个路径或路径片段的序列解析为一个绝对路径。相当于执行cd操作。
/被解析为根目录。
let myPath = path.resolve(__dirname,'/img/so'); let myPath2 = path.resolve(__dirname,'./img/so'); let myPath3=path.resolve('/foo/bar', './baz'); let myPath4=path.resolve('/foo/bar', '/tmp/file/'); console.log(__dirname); console.log(myPath); console.log(myPath2); console.log(myPath3); console.log(myPath4);
http://ibeetl.com/guide/ 1. 什么是Beetl
Beetl目前版本是2.8.1,相对于其他java模板引擎,具有功能齐全,语法直观,性能超高,以及编写的模板容易维护等特点。使得开发和维护模板有很好的体验。是新一代的模板引擎。总得来说,它的特性如下:
功能完备:作为主流模板引擎,Beetl具有相当多的功能和其他模板引擎不具备的功能。适用于各种应用场景,从对响应速度有很高要求的大网站到功能繁多的CMS管理系统都适合。Beetl本身还具有很多独特功能来完成模板编写和维护,这是其他模板引擎所不具有的。 非常简单:类似Javascript语法和习俗,只要半小时就能通过半学半猜完全掌握用法。拒绝其他模板引擎那种非人性化的语法和习俗。同时也能支持html 标签,使得开发CMS系统比较容易 超高的性能:Beetl 远超过主流java模板引擎性能(引擎性能5-6倍与freemaker,2倍于JSP。参考附录),而且消耗较低的CPU。 易于整合:Beetl能很容易的与各种web框架整合,如Spring MVC,JFinal,Struts,Nutz,Jodd,Servlet等。 支持模板单独开发和测试,即在MVC架构中,即使没有M和C部分,也能开发和测试模板。 扩展和个性化:Beetl支持自定义方法,格式化函数,虚拟属性,标签,和HTML标签. 同时Beetl也支持自定义占位符和控制语句起始符号也支持使用者完全可以打造适合自己的工具包。 可以扩展为脚本引擎,规则引擎,能定制引擎从而实现高级功能。 关于性能 在使用FastRuntimeEngine情况下,通过与主流模板引擎Freemarker,Vecloity以及JSP对比,Beetl6倍于Freemarker,2倍于JSP。这是因为宏观上,通过了优化的渲染引擎,IO的二进制输出,字节码属性访问增强,微观上,通过一维数组保存上下文Context,静态文本合并处理,通过重复使用字节数组来防止java频繁的创建和销毁数组,还使用模板缓存,运行时优化等方法。详情参考附录 独特功能 Beetl有些功能是发展了10多年的模板引擎所不具备的,这些功能非常利于模板的开发和维护,如下 自定义占位符和控制语句起始符号,这有利于减小模板语法对模板的倾入性,比如在html模板中,如果定义控制语句符号是<!--:和-->,那么,大部分模板文件都能通过浏览器打开。有的使用者仅仅采用了单个符号@ (或者单个符号“~”)以及回车换号作为控制语句起始符号,这又能提高开发效率 可单独测试的模板。无需真正的控制层和模型层,Beetl的模板就可以单独开发和测试 同时支持较为松散的MVC和严格的MVC,如果在模板语言里嵌入计算表达式,复杂条件表达式,以及函数调用有干涉业务逻辑嫌疑,你可以禁止使用这些语法。 强大的安全输出,通过安全输出符号!,能在模板变量,变量属性引用,for循环,占位符输出,try-catch中等各个地方提供安全输出,保证渲染正常。 模板变量:运行将模板的某一部分输出像js那样赋值给一个变量,稍后再处理。利用模板变量能完成非常复杂的页面布局(简单的布局可使用include,layout标签函数) 类型推测,能在运行的时候推测模板变量类型,从而优化性能,也可以通过注解的方法显示的说明模板变量属性(这是非必须的,但有助于IDE自动提示功能) 可插拔的设计,错误信息提示,模板引擎缓存机制,模板资源管理,本地调用的安全管理器,严格MVC限制,模板引擎本身都有默认的实现,但又完全可以自定义以适合特定需求 增强的语法,如for-elsefor, select-case,安全输出符号!,省略的三元表达式 等,这些语法特别适合模板开发 局部渲染技术,结合现在js的ajax技术。 性能超高,具有最快的模板解释引擎,同时,又有较低的CPU消耗。5-6倍于国内使用的Freemaker。适合各类模板应用,如代码生成工具,CMS系统,普通网站,超高访问量的门户系统,和富客户端JS框架整合的后台管理应用 小白如何开始 需要通读基本用法,大部分都是讲解语法,而语法跟js很接近,所以可以快速预览,但Beetl是针对模板设计, 所以像安全输出,标签和html标签,全局变量,临时变量和共享变量,布局技术,以及直接调用java代码等还需要认真读一遍。 如果从事web开发,还需要阅读web集成里的第一节“web提供的全局变量”,如果web里还使用ajax技术,可以阅读“整合ajax的局部渲染技术”。 包含有spring,jfinal,jodd,struts 等demo可以作为参考学习用https://git.oschina.net/xiandafu 任何问题,都可以在ibeetl.com 社区上提问。目前答复率是100%,提问需要详细说明自己的期望,出错信息,附上代码或者图片 联系作者 作者:闲.大赋 (李家智)等(参考附录查看代码贡献者) QQ技术交流群:219324263(满) 636321496 邮件:xiandafu@126.com Beetl社区:bbs.ibeetl.com 源码主页:https://github.com/javamonkey/beetl2.0 在线体验和代码分享 http://ibeetl.com/beetlonline/ 基本用法 2.1. 安装 如果使用maven,请使用如下坐标
com.ibeetl beetl 2.8.1 如果非maven工程,直接下载http://git.oschina.net/xiandafu/beetl2.0/attach_files 2.2. 从GroupTemplate开始
StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader(); Configuration cfg = Configuration.defaultConfiguration(); GroupTemplate gt = new GroupTemplate(resourceLoader, cfg); Template t = gt.
第一步,打开文件信息的选项卡,点击自定义功能区,勾选开发工具。如下图: 接下来我来演示宏的录制过程。 1、打开一个文件点击录制宏,为宏命名,设置快捷键,点击确定。 2、点击A1单元格的工号,然后点击“使用相对引用”,然后选中第一行开始复制,选中第三行点击右键,点击“插入复制的单元格”,然后点击停止录制宏。 3、点击插入选项卡,插入一个表单控件,选择要运行的宏,点击确定。选中工号,点击按钮即可完成宏的录制。
在android打包发布的时候,需要对app进行压缩,混淆,去除无效文件等,以保证发布出去的app占用资源尽可能的小。因此需要我们对gradle进行必要的配置(以android studio打包为例)。
1、build.gradle 配置 buildTypes{ debug { //多余的参数 minifyEnabled false zipAlignEnabled false shrinkResources false signingConfig signingConfigs.debug // 显示Log buildConfigField "boolean", "LOG_DEBUG", "true" } release { minifyEnabled true //混淆 zipAlignEnabled true //Zipalign优化 shrinkResources false //删除无用资源 signingConfig signingConfigs.release // 显示Log buildConfigField "boolean", "LOG_DEBUG", "false" proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } release版本为发布版本,因此设置了minifyEnabled true,zipAlignEnabled true,shrinkResources true。其中proguard-rules.pro是需要我们自己根据项目编写的混淆文件。
2、proguard-rules.pro混淆文件编写(网上都有,就不贴了) 3、常见transformClassesAndResourcesWithProguardForRelease’.错误 这个问题是在说你在混淆打包的时候有些类有可能找不着,所以会报错,和warning 解决的办法: 找到报warning的类都给他在你的proguard-rules.pro混淆器文件中 添加代码-dontwarn 包名+类名.**; 给取消掉warning就可以了,如果你不想那个类被混淆,那就添加代码:-keep class 包名+类名{;}或者包名.*{*;} 当然也可以在proguard-rules.pro添加-ignorewarning ,这个是“屏蔽所有警告” 。 因此打出的包可能会出现必要代码被混淆导致项目奔溃而无法正常运行,因此个人建议,最好不要加这句代码,遇到什么错误什么警告,对应去解决即可,解决完了自然可以打包成功了。
4、解决 The same input jar is specified twice 问题 在 Android Studio 中, build.
因为项目原因,不多说上代码
public class CommonCalendarView extends FrameLayout implements View.OnClickListener { private ViewPager mViewPager; private TextView mMonthTv; private Context mContext; private ImageButton mLeftMonthBtn; private ImageButton mRightMonthBtn; private SparseArray<GridView> mViewMap = new SparseArray<>(); private Map<String, List> mYearMonthMap; private DatePickerController mController; private CalendarAdapter adapter; private Date maxDate; private Date minDate; public void setMaxDate(Date maxDate) { this.maxDate = maxDate; } public void setMinDate(Date minDate) { this.minDate = minDate; } public CommonCalendarView(Context context) { this(context,null); } public CommonCalendarView(Context context, AttributeSet attrs) { this(context, attrs,0); } public CommonCalendarView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; } public void init(DatePickerController controller){ if (controller==null){ mController = new DatePickerController() { @Override public int getMaxYear() { return DateUtils.
题目:最小栈
题目描述 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) – 将元素x推入栈中。pop() – 删除栈顶的元素。top() – 获取栈顶元素。getMin() – 检索栈中的最小元素。 示例:
MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.getMin(); –> 返回 -3. minStack.pop(); minStack.top(); –> 返回 0. minStack.getMin(); –> 返回 -2.
#include <stdio.h> #include <stack> class MinStack { public: /** initialize your data structure here. */ MinStack() { } void push(int x) { //将数据压入数据栈 _data.push(x); //将数据压入数据栈 if(_min.empty()) //如果 { _min.push(x); } else{ if(x>_min.top()) { x = _min.
在开始我们的正文之前,你需要先了解一下原码、反码、补码这三个概念以及这三者之间的相互转换方式。 在有了一定的了解之后,我们开始我们的介绍。在本文中,我们以短整型为例,给大家介绍该类型的取值范围的计算方式,以及原理。 首先默认情况下,unsigned int 占用2个字节(跟具体的编译器和操作系统有关),也就是16位。 在计算机存储的数据中,都是用0和1表示的,并且是用补码表示的(很重要)。
在实际的存储过程中,我们规定表示负数的时候,最高位为符号位(负数的符号位为1),那么对于这个16位,我们能表示的最小的负数应当是这个样子的:1000 0000 0000 0000 ,我们在前面说过,在计算机中,是以补码形式存储的,所以但是在计算机中负数是用补码(原码符号位不变,其余位取反,然后加1)表示的,所以我们要把它转换成原码再和十进制转换。我们发现在转换成原码之后,依旧是1000 0000 0000 0000。 我们现在假想一个问题,如果我们有+0和-0这两种情况,我们用二进制该怎么表示呢? 对于+0,它应该是0000 0000 0000 0000; 对于-0,它应该是1000 0000 0000 0000。 但是无论+0还是-0,从数学的角度它都应该是0,但是在计算机的二进制存储中我们却发现-0的二进制竟然和16位二进制存储中的最小值(即前面提到的1000 0000 0000 0000)一样,但是0肯定不是这里的最小值啊,于是为了解决这个问题,我们规定,1000 0000 0000 0000表示16位中的最小值,即-32768。
表示正数时,最高位为符号位(正数的符号位为0),最大的正数为0111 1111 1111 1111 即2^15 - 1 = 32767。
所以16位的短整型所能表示的范围是-32768 - 32767。
二叉树遍历分为三种:前序、中序、后序,其中序遍历最为重要。为啥叫这个名字?是根据根节点的顺序命名的。
比如上图正常的一个满节点,A:根节点、B:左节点、C:右节点,前序顺序是ABC(根节点排最先,然后同级先左后右);中序顺序是BAC(先左后根最后右);后序顺序是BCA(先左后右最后根)。
比如上图二叉树遍历结果
前序遍历:ABCDEFGHK
中序遍历:BDCAEHGKF
后序遍历:DCBHKGFEA
分析中序遍历如下图,中序比较重要(java很多树排序是基于中序,后面讲解分析)
此文章已永久迁移至个人博客网站,为不影响使用,请打开如下网址访问
https://www.iiter.cn/blogs/28
计算Java对象的字节大小 Java基本类型长度及对应对象的字节长度 基本类型长度the size of an objectInt416Short216Long824Byte116Character116Float416Double824 System.out.println("Integer: " + ObjectSizeCalculator.getObjectSize(Integer.valueOf(122))); System.out.println("Long: " + ObjectSizeCalculator.getObjectSize(Long.valueOf(122L))); System.out.println("Double: " + ObjectSizeCalculator.getObjectSize(Double.valueOf(122.22))); System.out.println("Float: " + ObjectSizeCalculator.getObjectSize(Float.valueOf(122.22f))); System.out.println("Boolean: " + ObjectSizeCalculator.getObjectSize(Boolean.valueOf(false))); System.out.println("Character: " + ObjectSizeCalculator.getObjectSize(Character.valueOf('a'))); System.out.println("Short: " + ObjectSizeCalculator.getObjectSize(Short.valueOf("1"))); System.out.println("Byte: " + ObjectSizeCalculator.getObjectSize(Byte.valueOf("1"))); System.out.println("Date: " + ObjectSizeCalculator.getObjectSize(new Date())); System.out.println("Timestamp: " + ObjectSizeCalculator.getObjectSize(new Timestamp(System.currentTimeMillis()))); Map<String, Object> map = new HashMap<>(); map.put("11", 11); map.put("22", "22"); map.put("33", 33L); map.put("44", 44.44); System.out.println("Map: " + ObjectSizeCalculator.getObjectSize(map)); 结果:
Integer: 16 Long: 24 Double: 24 Float: 16 Boolean: 16 Character: 16 Short: 16 Byte: 16 Date: 24 Timestamp: 32 Map: 512 ObjectSizeCalculator类 jdk.
一.函数题
6-1 使用函数求素数和(20 分) 本题要求实现一个判断素数的简单函数、以及利用该函数计算给定区间内素数和的函数。
素数就是只能被1和自身整除的正整数。注意:1不是素数,2是素数。
函数接口定义: int prime( int p ); int PrimeSum( int m, int n ); 其中函数prime当用户传入参数p为素数时返回1,否则返回0;函数PrimeSum返回区间[m, n]内所有素数的和。题目保证用户传入的参数m≤n。
裁判测试程序样例: #include <stdio.h> #include <math.h> int prime( int p ); int PrimeSum( int m, int n ); int main() { int m, n, p; scanf("%d %d", &m, &n); printf("Sum of ( "); for( p=m; p<=n; p++ ) { if( prime(p) != 0 ) printf("%d ", p); } printf(") = %d\n"
var obj = { key1:1, key2:2, key3:3 }; Object.getOwnPropertyNames(obj).length Object.keys(obj).length
一、数据匹配步骤 1. 确定两个表格之间的关系。 在这里咱们可以叫【数据源表】和【被填充表】,数据源表就是被拿来参照的,被填充表就是咱们自己要填充信息的表。二者之间的联系:【数据源表】中的数据有一列和【被填充表】中的一列是有相同内容。在这里咱们可以称这一列为【公共列】。
2.明确好了两表关系后,就开始操作了。 下面我以两个表格为例。第一张图片上面的表格为【被填充表】,第二张图片为【数据源表】
3. 插入公式 在单元格内输入等号——点击fx选择函数——选择VLOOKUP——确定,具体请看下图:
4.设置函数参数(编辑公式): 第一行:Lookup_value 需要选中【被填充表】中的【公共列】中与被填充单元格相对应的单元格,这里应该是D3(图片上是B3是错误的)
第二行:Table_array 需要选中数据源表中的被匹配区域(为了操作方便可以多选,这里我们选AB两列)
第三行: Col_index_num 需要我们填充与【被填充表】的被填充列与在【数据源表】数据相同的那一列所在的列角标(A列的角标为1,B列的角标为2以此类推。。。)这里我们填2。
第四行:Range_lookup 这里填0
5. 点击确定,你就会看到,匹配过来的数据。
然后我们在匹配过来的数据的单元格里面,按住ctrl 向下拉直到你想要的数据完全匹配出来。
到这里步骤就完了,但是对于新手来说可能会出各种问题,后面就给大家介绍几个容易出现的问题和解决方法。
1.ConcurrentHashmap简介 在使用HashMap时在多线程情况下扩容会出现CPU接近100%的情况,因为hashmap并不是线程安全的,通常我们可以使用在java体系中古老的hashtable类,该类基本上所有的方法都采用synchronized进行线程安全的控制,可想而知,在高并发的情况下,每次只有一个线程能够获取对象监视器锁,这样的并发性能的确不令人满意。另外一种方式通过Collections的Map<K,V> synchronizedMap(Map<K,V> m)将hashmap包装成一个线程安全的map。比如SynchronzedMap的put方法源码为:
public V put(K key, V value) { synchronized (mutex) {return m.put(key, value);} } 复制代码 实际上SynchronizedMap实现依然是采用synchronized独占式锁进行线程安全的并发控制的。同样,这种方案的性能也是令人不太满意的。针对这种境况,Doug Lea大师不遗余力的为我们创造了一些线程安全的并发容器,让每一个java开发人员倍感幸福。相对于hashmap来说,ConcurrentHashMap就是线程安全的map,其中利用了锁分段的思想提高了并发度。
ConcurrentHashMap在JDK1.6的版本网上资料很多,有兴趣的可以去看看。 JDK 1.6版本关键要素:
segment继承了ReentrantLock充当锁的角色,为每一个segment提供了线程安全的保障;segment维护了哈希散列表的若干个桶,每个桶由HashEntry构成的链表。 而到了JDK 1.8的ConcurrentHashMap就有了很大的变化,光是代码量就足足增加了很多。1.8版本舍弃了segment,并且大量使用了synchronized,以及CAS无锁操作以保证ConcurrentHashMap操作的线程安全性。至于为什么不用ReentrantLock而是Synchronzied呢?实际上,synchronzied做了很多的优化,包括偏向锁,轻量级锁,重量级锁,可以依次向上升级锁状态,但不能降级(关于synchronized可以看这篇文章),因此,使用synchronized相较于ReentrantLock的性能会持平甚至在某些情况更优,具体的性能测试可以去网上查阅一些资料。另外,底层数据结构改变为采用数组+链表+红黑树的数据形式。
2.关键属性及类 在了解ConcurrentHashMap的具体方法实现前,我们需要系统的来看一下几个关键的地方。
ConcurrentHashMap的关键属性
table volatile Node<K,V>[] table://装载Node的数组,作为ConcurrentHashMap的数据容器,采用懒加载的方式,直到第一次插入数据的时候才会进行初始化操作,数组的大小总是为2的幂次方。
nextTable volatile Node<K,V>[] nextTable; //扩容时使用,平时为null,只有在扩容的时候才为非null
sizeCtl volatile int sizeCtl; 该属性用来控制table数组的大小,根据是否初始化和是否正在扩容有几种情况: **当值为负数时:**如果为-1表示正在初始化,如果为-N则表示当前正有N-1个线程进行扩容操作; **当值为正数时:**如果当前数组为null的话表示table在初始化过程中,sizeCtl表示为需要新建数组的长度; 若已经初始化了,表示当前数据容器(table数组)可用容量也可以理解成临界值(插入节点数超过了该临界值就需要扩容),具体指为数组的长度n 乘以 加载因子loadFactor; 当值为0时,即数组长度为默认初始值。
sun.misc.Unsafe U 在ConcurrentHashMapde的实现中可以看到大量的U.compareAndSwapXXXX的方法去修改ConcurrentHashMap的一些属性。这些方法实际上是利用了CAS算法保证了线程安全性,这是一种乐观策略,假设每一次操作都不会产生冲突,当且仅当冲突发生的时候再去尝试。而CAS操作依赖于现代处理器指令集,通过底层CMPXCHG指令实现。CAS(V,O,N)核心思想为:若当前变量实际值V与期望的旧值O相同,则表明该变量没被其他线程进行修改,因此可以安全的将新值N赋值给变量;若当前变量实际值V与期望的旧值O不相同,则表明该变量已经被其他线程做了处理,此时将新值N赋给变量操作就是不安全的,在进行重试。而在大量的同步组件和并发容器的实现中使用CAS是通过sun.misc.Unsafe类实现的,该类提供了一些可以直接操控内存和线程的底层操作,可以理解为java中的“指针”。该成员变量的获取是在静态代码块中:
static { try { U = sun.misc.Unsafe.getUnsafe(); ....... } catch (Exception e) { throw new Error(e); } } 复制代码 ConcurrentHashMap中关键内部类
ORB-SLAM是由Raul Mur-Artal,J. M. M. Montiel和Juan D. Tardos于2015年发表在IEEE Transactions on Robotics。项目主页网址为: http://webdiis.unizar.es/~raulmur/orbslam/。 ORB-SLAM是一个基于特征点的实时单目SLAM系统,在大规模的、小规模的、室内室外的环境都可以运行。该系统对剧烈运动也很鲁棒,支持宽基线的闭环检测和重定位,包括全自动初始化。该系统包含了所有SLAM系统共有的模块: 跟踪(Tracking)、建图(Mapping)、重定位(Relocalization)、闭环检测(Loop closing)。由于ORB-SLAM系统是基于特征点的SLAM系统,故其能够实时计算出相机的轨线,并生成场景的稀疏三维重建结果。ORB-SLAM2在ORB-SLAM的基础上,还支持标定后的双目相机和RGB-D相机。 ORB-SLAM的贡献: 系统架构 ORB-SLAM其中的关键点如下图所示: 可以看到ORB-SLAM主要分为三个线程进行,也就是论文中的下图所示的,分别是Tracking、LocalMapping和LoopClosing。ORB-SLAM2的工程非常清晰漂亮,三个线程分别存放在对应的三个文件中,分别是Tracking.cpp、LocalMapping.cpp和LoopClosing.cpp文件中,很容易找到。 (1)跟踪(Tracking) 这一部分主要工作是从图像中提取ORB特征,根据上一帧进行姿态估计,或者进行通过全局重定位初始化位姿,然后跟踪已经重建的局部地图,优化位姿,再根据一些规则确定新的关键帧。 (2)建图(LocalMapping) 这一部分主要完成局部地图构建。包括对关键帧的插入,验证最近生成的地图点并进行筛选,然后生成新的地图点,使用局部捆集调整(Local BA),最后再对插入的关键帧进行筛选,去除多余的关键帧。
(3)闭环检测(LoopClosing) 这一部分主要分为两个过程,分别是闭环探测和闭环校正。闭环检测先使用WOB进行探测,然后通过Sim3算法计算相似变换。闭环校正,主要是闭环融合和Essential Graph的图优化。 一、整体框架 ORB_SLAM的代码非常整齐,简洁,便于阅读。由于我将使用其做室外场景的单目SLAM,所以我们从mono_kitti.cc这个主程序来看整个代码。为了更加方便阅读,我将其中的关键步骤做成思维导图,这样就可以一目了然了。喜欢的朋友请点赞!~ 如下图所示,程序在接收参数传递的参数后,就能够找到存放数据和参数的目录,开始运行。 (1)首先使用LoadImages读取图片目录和时间戳文件 (2)创建ORB_SLAM2::System对象 (3)循环读取数据 (3.1)读取图片 (3.2)读取时间戳 (3.3)将图片传给SLAM系统 (4)关闭SLAM系统 (5)将相机轨线保存到硬盘中
二、SLAM系统的创建 在主函数中,我们创建了一个ORB_SLAM2::System的对象SLAM,这个时候就会进入到SLAM系统的主接口System.cc。这个代码是所有调用SLAM系统的主入口,在这里,我们将看到前面博客所说的ORB_SLAM的三大模块:Tracking、Mapping和LoopClosing。如下图所示: 我们可以看到在这个对象的实例化过程中,我们创建了以下对象: (1)创建了ORB词袋的对象
(2)创建了关键帧的数据库 (3)创建地图对象 (4)创建两个显示窗口 (5)初始化Tracking对象 (6)初始化Local Mapping对象,并开启线程运行 (7)初始化Loop Closing对象,并开启线程运行 (8)初始化窗口,开启线程显示图像和地图点 在这个实例化的过程中,我们开启了三个线程,分别是Local Mapping、Loop Closing和窗口显示的线程,那第一步Tracking在哪里运行呢?
三、Tracking的运行 上面我们提到Tracking的运行入口,回顾第一部分,我们在循环读取图片的时候,调用了一个SLAM.TrackMonocular()函数,这个函数就是在主线程里调用Tracking的函数入口了。所以Tracking是运行在主线程中,并且在每次读取一帧新的图像时运行一次。如下图所示: 可以看到,跟了两步之后,就能很清晰地看到,程序将读取的图片转成灰度图,然后对帧进行特征点检测,就直接调用Tracking.cc中的Track()函数,进行跟踪。另外要注意的是,由于使用的是单目相机,所以在跟踪时需要判断是否初始化或有没有前序关键帧,如果没有,使用mpIniORBextractor的参数进行特征点检测。
自动地图初始化 系统的第一步是初始化,ORB_SLAM使用的是一种自动初始化方法。这里同时计算两个模型:用于平面场景的单应性矩阵H和用于非平面场景的基础矩阵F,然后通过一个评分规则来选择合适的模型,恢复相机的旋转矩阵R和平移向量t。 一、找到初始对应点 在当前帧Fc
中提取ORB特征点,与参考帧Fr进行匹配。如果匹配点对数过少,就重置参考帧。这一步骤在Tracking.cc中的Tracking::MonocularInitialization函数中。
int nmatches = matcher.SearchForInitialization(mInitialFrame,mCurrentFrame,mvbPrevMatched,mvIniMatches,100); 1 nmatches表示匹配到的对应点对数。
二、同时计算两个模型 在找到对应点之后,开始调用Initializer.cc中的Initializer::Initialized函数进行初始化工作。为了计算R和t,ORB_SLAM为了针对平面和非平面场景选择最合适的模型,同时开启了两个线程,分别计算单应性矩阵Hcr
BSTR实际上就是一个COM字符串,标准BSTR是一个有长度前缀和null结束符的OLECHAR数组。BSTR的前4字节是一个表示字符串长度的前缀。BSTR长度域的值是字符串的字节数,并且不包括0结束符
#include <comutil.h>
#include <string>
#pragma comment(lib, "comsuppw.lib")
//BSTR转string
BSTR bstrText = ::SysAllocString(L"Test");
string str = _com_util::ConvertBSTRToString(bstrText); SysFreeString(bstrText); //BSTR转char*
BSTR bstrText = ::SysAllocString(L"Test");
char* lpszText = _com_util::ConvertBSTRToString(bstrText); SysFreeString(bstrText); delete[] lpszText; //char*转BSTR
char* lpszText = "Test"; BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText); //string转BSTR
string str = "Test"; BSTR bstrText = _com_util::ConvertStringToBSTR(str);
Pytorch - Cross Entropy Loss Pytorch 提供的交叉熵相关的函数有:
torch.nn.CrossEntropyLoss
torch.nn.KLDivLoss
torch.nn.BCELoss
torch.nn.BCEWithLogitsLoss
torch.nn.MultiLabelSoftMarginLoss
1. CrossEntropyLoss class torch.nn.CrossEntropyLoss(weight=None, size_average=True, ignore_index=-100, reduce=True)[source] 作用
针对单目标分类问题, 结合了 nn.LogSoftmax() 和 nn.NLLLoss() 来计算 loss.
用于训练 C C 类别classes 的分类问题. 参数 weight 是 1D Tensor, 分别对应每个类别class 的权重. 对于类别不平衡的训练数据集比较有用.
输入input 包含了每一类别的概率或score.
输入 input Tensor 的大小是 (minibatch,C)(minibatch,C) 或 (minibatch,C,d1,d2,...,dK) ( m i n i b a t c h , C , d 1 , d 2 , .
自然语言处理方向的论文仿真到现在,有以下想法: 1. 很多模型都为启发式算法,从直观上很好理解,但是对于大多数人来说,就是一个黑盒,70%时间都在处理数据和调参。 2. 在数据竞赛中,常用的模型就是CNN和RNN,先调出baseline,然后再进行模型融合(model ensemble)。在以上步骤的约束下,数据竞赛比的就是设备的计算能力和个人的调参能力。 3. 在自然语言处理与NLP实战的一系列文章中,参考brightmart的项目分别介绍了CNN、RNN、charCnn、charRNN、RCNN、ATTENTION、Dynamic Memory Network、EntityNetwork等模型。前一段时间周围同学都在参加知乎“看山杯”数据竞赛,现在刚好可以拿来将所积累的知识用在实战中。 4. 该比赛在笔记本或者台式机上根本玩不转,理想的实验环境肯定要有GPU。实验室只有一台128G内存的服务器。对我个人而言,已经进入到研二,等待实验室购买GPU肯定不现实了,但还是想努力地在一些数据竞赛中取得成绩。
数据集 数据特征 数据经过脱敏处理,看到的不是“如何评价2017知乎看山杯机器学习比赛”,而是“w2w34w234w54w909w2343w1”这种经过映射的词的形式,或者是”c13c44c4c5642c782c934c02c2309c42c13c234c97c8425c98c4c340”这种经过映射的字的形式。因为词和字经过脱敏处理,所以无法使用第三方的词向量,官方特地提供了预训练好的词向量,即char_embedding.txt和word_embedding.txt ,都是256 维。主办方提供了1999个类别的描述和类别之间的父子关系(比如机器学习的父话题是人工智能,统计学和计算机科学),但这个知识没有用上。训练集包含约300万条问题的标题(title),问题的描述(description)和问题的话题(topic)测试集包含21万条问题的标题(title),问题的描述(description),需要给出最有可能的5个话题(topic) 数据分析 拿到数据以后,首先要对数据进行分析。采用深度学习模型,需要对句子进行截断和填充,这个就需要找到一个合适的长度。 对title的word组成char组成进行长度分析,如下图:
同理需要对content进行长度分析。综上,可以的到下表:
对数据进行预处理,即截断和补齐,长度大约为平均长度的两倍左右。另外,因为数据量很大,如果不能保证一次跑完整个预处理过程,最好还是需要将过程中需要的变量持久化,通过pickle进行保存。
数据处理 数据处理过程包括以下几步: 1. 得到word_embedding和char_embedding的变量,并保存成文件。源数据中给出的embedding的格式为: 刚好是python中word2vec工具能处理的文件格式,所以通过:
wv = word2vec.load('../raw_data/word_embedding.txt') 1 就能得到embedding变量,将数据持久化即可完成第一步。 2. 得到topic2id的变量。在数据处理中,pandas的Series非常好用。源文件中,每一个文本都对应着一个或多个topic,topic的总数为1999,也就是说总共包含1999类文本。将topic按出现频率从大到小进行排号,并保存在文件中。 3. 将title和content中的word或者char转换为对应的id。第一步我们得到word或者char转id的Series,第二步我们得到topic转id的Series,第三步我们就需要将问题的title和content中的word或者char转为id。这一步产生的中间变量会有大约4-5个G,所以需要在做项目之前就提前准备好至少100G的磁盘。 4. 将数据集分为train,valid和test,并进行打包存储。对于只有cpu的同学,训练一个epoch大约就需要一两天的时间,训练到理想效果可能七八天就过去了,所以最好还是将数据集都提前准备好,模型训练的时候直接进行提取。
注意:在对train数据进行处理时,对于没有content的数据,使用title进行填充。填充完以后没有title的数据就可以直接drop了。 对eval数据进行处理时,对于没有content的数据,使用title进行填充。对于没有title的数据,使用content进行填充。确保每一个最终提交的eval,都会有结果。
模型 1. FastText fastText 是 word2vec 作者 Mikolov 转战 Facebook 后16年7月刚发表的一篇论文 Bag of Tricks for Efficient Text Classification。fastText极致简单,和word2vec中的CBOW模型思路很像,模型图见下: 原理是把句子中所有的词向量进行平均(某种意义上可以理解为只有一个avg pooling特殊CNN),然后直接接 softmax 层。其实文章也加入了一些 n-gram 特征的 trick 来捕获局部序列信息。文章倒没太多信息量,算是“水文”吧,带来的思考是文本分类问题是有一些“线性”问题的部分,也就是说不必做过多的非线性转换、特征组合即可捕获很多分类信息,因此有些任务即便简单的模型便可以搞定了。
2. TextCNN TextCNN的开篇之作是Convolutional Neural Networks for Sentence Classification,在github上实现代码。该代码符合tensorflow的编程规范,是入门自然语言处理与NLP很好的切入点。 14年的这篇文章提出TextCNN的结构如下图。fastText 中的网络结果是完全没有考虑词序信息的,而TextCNN用的 n-gram 特征 trick 恰恰说明了局部序列信息的重要意义。卷积神经网络(CNN Convolutional Neural Network)最初在图像领域取得了巨大成功,CNN原理就不讲了,核心点在于可以捕捉局部相关性,具体到文本分类任务中可以利用CNN来提取句子中类似 n-gram 的关键信息。 3.
录制一个宏: 实现:将表单中的表头插入每一行 step 1:如何打开EXCEL中的宏选项 你需要点击文件—>选项—>自定义功能区—>勾选“加载项”即可。 然而需要注意的是:使用宏是有安全性限制的,Office办公软件的默认宏安全性设置为高,是无法启用编写好的 VBA 程序代码的。所以通过如下方式将安全性降低: 需要点击文件—>选项—>信任中心—>宏设置—>勾选“信任对VBA工程对象模型的访问”即可。 step 2:如何使用宏录制实现我们的目的 首先需要先选中表头行(一定要在录制开始前选中表头行,因为如果录制完后再选中第一行,就会报错“1004”) 然后需要将“相对引用”打开 接下来就可以正式录制啦 录制开始前需要填写宏名称,并且给宏一个快捷键,毕竟你不会想要全程用鼠标操作 当你开始录制之后,对录制前已选中的表头行直接复制(Ctrl+C),并且从第三行起插入(符合EXCEL的使用规则) 然后直接停止录制,我们就完成了这个宏的录制全过程 step 3:录制完后实现你的宏 可以通过快捷键直接实现 这样还不够简便,于是我们可以添加一个按钮,点击即可执行宏 以下是按钮的操作效果 step 4:实现宏的自动化 如果以上部分一步步执行仍然不能让你满意,那就需要改进这个宏,实现自动化 快捷键Alt+F11直接跳转进VBA编辑窗口 然后在这里添加两行命令即可(先判断一下原始数据有多少行) 这两行的意思是:利用For循环,建立一个计数变量,然后让该程序运行21次然后跳出。 这样以来就可以实现自动化 最终我们实现了将表头添加到每一行之间的目的。
使用ACache也可以设置缓存时间,但ACache在清缓存的时候会被清空。 SharedPreferences存储默认都是无时间限制的。 大概思路是,存储的时候记录当前时间,要存多久。取数据的时候判断这个数据已经存储了多久,如果超过设置的存储时间,就获取默认值。 首先,我们需要一个存储的model——SpSaveModel
public class SpSaveModel<T> implements Serializable{ private int saveTime; private T value; private long currentTime; public SpSaveModel() { } public SpSaveModel(int saveTime, T value,long currentTime) { this.saveTime = saveTime; this.value = value; this.currentTime=currentTime; } public long getCurrentTime() { return currentTime; } public void setCurrentTime(long currentTime) { this.currentTime = currentTime; } public int getSaveTime() { return saveTime; } public void setSaveTime(int saveTime) { this.saveTime = saveTime; } public T getValue() { return value; } public void setValue(T value) { this.
1、引入js文件
在用的那一页,引入文件
相应的js文件里面,必须是暴露出来的
2、引入组件
3、引入外部组件
4、引入外部js插件
Tomcat7.0.22在Windows下详细配置过程 一、JDK1.7安装 1、下载jdk,下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u1-download-513651.html 2、添加系统环境变量,我的电脑->属性->高级->环境变量(如果添加的环境变量已经存在,点击“编辑”添加,否则点击“新建”添加) (1)变量名: JAVA_HOME 变量值: D:\Program Files\Java\jdk1.6.0_29(点击“新建”,输入变量名、变量值,变量值末不需要分号) (2)变量名: CLASSPATH 变量值: D:\Program Files\Java\jdk1.6.0_29\lib\dt.jar;D:\Program Files\Java\jdk1.6.0_29\lib\tools.jar(“新建”,变量值末不需要分号) (3)变量名: Path 变量值: D:\Program Files\Java\jdk1.6.0_29\bin(“编辑”,变量值使用英文分号隔开,变量值末不需要分号) 3、“开始”->“运行”->输入cmd,在命令提示符中输入“java -version”,“java”,“javac”几个命令,出现画面,说明环境变量配置成功 ------------------------------------------------------------------------------------------------------------------ 二、Tomcat7.0.22安装配置 1、下载tomcat7.0.22 下载地址:http://tomcat.apache.org/download-70.cgi 2、添加系统环境变量,我的电脑->属性->高级系统设置->环境变量(操作同上) (1)变量名: CATALINA_BASE 变量值: D:\Program Files\apache-tomcat-7.0.22(Tomcat解压到的目录) (2)变量名: CATALINA_HOME 变量值: D:\Program Files\apache-tomcat-7.0.22 (3)变量名: CATALINA_TMPDIR 变量值: D:\Program Files\apache-tomcat-7.0.22\temp (4)变量名: Path 变量值:D:\Program Files\apache-tomcat-7.0.22\bin 3、运行Tomcat7.0.22,“开始”->“运行”->输入cmd,在命令提示符中输入 startup.bat,之后会弹出tomcat命令框,输出启动日志;打开浏览器输入http://localhost:8080/ ,如果进入tomcat欢迎界面,那么恭喜你,配置成功。 ------------------------------------------------------------------------------------------------------------------ 将Tomcat注册为系统服务: cmd 进入 Tomcat\bin目录 执行命令:service.bat install (service.bat remove为删除系统服务)
------------------------------------------------------------------------------------------------------------------
Tomcat启动窗口改名:
在bin目录下创建:
setenv.bat文件
写入:set TITLE=Tomcat7.0-8080
------------------------------------------------------------------------------------------------------------------
部署多个Tomcat:
如果现在一台机器上已经部署了一个tomcat服务,无论这个tomcat是否已经注册为服务了,或者没有注册windows服务,或者注册了,都没关系。都可以采用下面的方法实现。
如果该tomcat已经注册为windows服务了,从window的环境变量中找不到 CATALINA_HOME和CATALINA_BASE,也可以采用下面的方式实现。 当第一个tomcat启动后,后面tomcat的server.
Vysor可以把Android真机投影到PC端,也就是电脑上;手机端和PC端课同步操作;
Vysor是Chrome浏览器的插件,我们想要添加这个插件需要翻墙;
从这里可以直接下载:Vysor
首先切换到root用户:sudo
进入系统后修改文件:
/etc/systemd/system/network-online.target.wants/networking.service
修改命令:
sudo vim /etc/systemd/system/network-online.target.wants/networking.service
将里面的TimeoutStartSec=5min 修改为TimeoutStartSec=2sec
转载于:https://www.cnblogs.com/fan-xiong/p/8981921.html
VS2017安装的Python路径在该目录下C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64 pip安装应该以管理员身份进入cmd,进一步通过 cd 路径进入相应文件夹 1)更新Python应该在Python.exe文件夹下,完整路径C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64,该路径下python -m pip install --upgrade pip即可完成python更新最新版本 2)pip安装应该在pip.exe下,完整路径C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\Scripts,该路径下直接输入pip install tensorflow完成tensorflow安装。
2019独角兽企业重金招聘Python工程师标准>>> 《后端架构师技术图谱》 最后更新于20180427
数据结构 队列集合链表、数组字典、关联数组栈树 二叉树完全二叉树平衡二叉树二叉查找树(BST)红黑树B-,B+,B*树LSM 树BitSet常用算法 排序、查找算法 选择排序冒泡排序插入排序快速排序归并排序希尔排序堆排序计数排序桶排序基数排序二分查找Java 中的排序工具布隆过滤器字符串比较 KPM 算法深度优先、广度优先贪心算法回溯算法剪枝算法动态规划朴素贝叶斯推荐算法最小生成树算法最短路径算法并发 多线程线程安全一致性、事务 事务 ACID 特性事务的隔离级别锁 Java中的锁和同步类公平锁 & 非公平锁悲观锁 & 乐观锁 & CASABA 问题CopyOnWrite容器RingBuffer可重入锁 & 不可重入锁互斥锁 & 共享锁死锁操作系统 计算机原理进程线程协程Linux设计模式 设计模式的六大原则23种常见设计模式应用场景单例模式责任链模式MVCIOCAOPUML微服务思想 康威定律运维 & 统计 & 技术支持 常规监控APM统计分析持续集成(CI/CD) Jenkins环境分离自动化运维 Ansiblepuppetchef测试 TDD 理论单元测试压力测试全链路压测A/B Test虚拟化 KVMXenOpenVZ容器技术 Docker云技术 OpenStackDevOps文档管理中间件 Web Server NginxOpenRestyApache HttpdTomcat 架构原理调优方案Jetty缓存 本地缓存客户端缓存 MemcachedRedis 架构回收策略Tair消息队列 消息总线消息的顺序RabbitMQRocketMQActiveMQKafkaRedis 消息推送ZeroMQ定时调度 单机定时调度分布式定时调度RPC DubboThriftgRPC数据库中间件 Sharding Jdbc日志系统 日志搜集配置中心API 网关网络 协议 OSI 七层协议TCP/IPHTTPHTTP2.0HTTPS网络模型 EpollNIOkqueue连接和短连接框架零拷贝(Zero-copy)序列化(二进制协议) HessianProtobuf数据库 基础理论 数据库设计的三大范式MySQL 原理InnoDB优化索引 聚集索引, 非聚集索引复合索引自适应哈希索引(AHI)explainNoSQL MongoDBHbase搜索引擎 搜索引擎原理LuceneElasticsearchSolrsphinx性能 性能优化方法论容量评估CDN 网络连接池性能调优流式计算 StormFlinkKafka Stream应用场景Hadoop HDFSMapReduceYarnSpark安全 web 安全 XSSCSRFSQL 注入Hash Dos脚本注入漏洞扫描工具验证码DDoS 防范用户隐私信息保护加密解密 对称加密哈希算法非对称加密服务器安全数据安全 数据备份网络隔离 内外网分离登录跳板机授权 RBACOAuth2.
在使用ORDER BY根据某个字段进行排序时,当有好几条数据这个字段值相同时,oracle会如何处理呢? 答案是,随机处理。
SELECT * FROM (SELECT tt.*, ROWNUM AS rowno FROM ( SELECT t.* FROM AIMS_LIST_INFO t WHERE 1=1 ORDER BY t.date_updated DESC ) tt WHERE ROWNUM <= #{end}) table_alias WHERE table_alias.rowno > #{begin} 这是使用sql实现分页的代码,当数据为批量导入时,date_updated这个字段的值都是一样的,这时我们会发现,第一页即begin=0&end=5和第二页即begin=5&end=10时会出现重复数据。
注:如果直接运行上述sql,赋值begin=0&end=100,执行若干次,会发现每次排序结果都一致,然而,这就能证明随机性是错误的嘛?
赋值begin=0&end=100 赋值begin=0&end=50 注意观察0-50条数据,是一致的嘛?
不是!!! 因此,前一种现象显然是数据库自身缓存的缘故,相同的sql执行结果会直接取缓存,而不是直接执行。
解决方式:在ORDER BY t.date_updated DESC中增加一个查询条件,打破这种排序字段完全一致导致的随机排序结果即可。 我增加的是表的主键,由oracle默认生成的
RAWTOHEX(SYS_GUID()) 这是一个随机生成的具有唯一性的字段,这样应该可以避免排序字段完全一致造成的问题。
没有找到自己中意的数独游戏,于是自己做了一个,游戏只有77K大小,但是麻雀虽小,五脏俱全。数独游戏该有的功能基本上都有了。
欢迎大家提出改进建议,游戏会持续更新。
1,数独随机生成 2,可设置5种不同难度 3,有笔记功能 4,可用键盘进行游戏 5,有颜色提示 6,有错误次数统计 7,可自动保存上次游戏
帮助 1,点击中间区域选中一块空格 2,点击左侧数字将其放入空格中 3,点击中间数字可高亮显示数字 4,点击右侧数字可添加或移除笔记信息
快捷键 1,方向键 变更当前选中格 2,数字键 在空格中输入数字 3,Ctrl+数字键 在空格中输入或移除笔记
下载地址:https://pan.baidu.com/s/1sBiESVqTPBtb5b54ybHUoQ
在公司项目中,在做版本管理的时候,遇到了需要识别被管理的APK(安卓应用包)和IPA(苹果应用包)的情况,需要在上传的时候识别并导入包的一些信息到数据库中,并作出管理。
一、如何识别信息 在我开始研究这个的解决方法的时候,同事告诉我,网上有现成的工具类,可以直接读取各种安装包的信息。于是上网搜索了一下,果然解决方案很多,先不说优劣,从解决的思路上来,可以发现,他们的解决方法都是千篇一律的。
和众多的项目一样,在苹果和安卓的项目中,也有很多的版本信息,那么这些都存储在哪里了呢?在每个我们打好的包里面,其实都有一个专门标注版本信息和版权,描述的文件,如果我们用winrar或者其他解压缩软件把安装包解压缩之后,我们可以得到里面的很多信息,然后一般我们都会在软件的最外层发现一个.xml的文件来看到我们的版本信息(一般都有加密)。
所以我们获得版本信息的来源就是要从安装包中提取xml的文件,然后通过解析xml文件中的特殊节点来获得我们所需要的信息。具体思路就是 解包(类似zip)->读取文件->把信息放入构造的实体中->从实体中获得数据
因为各种版本的安卓应用所用的AndroidStudio和SDK都是不同的,所以我们在解析的时候也会有稍许的不同,好在有兼容的存在,还有对于各种版本的识别网上都有处理。
二、开始动手
我们在开始之前首先需要引入两个jar包,分别是dd-plist-1.16.jar(ios的识别)和apk-parser-2.5.3.jar(安卓的识别)
下载地址:https://download.csdn.net/download/tr1912/10383172
我们在引入jar包的时候直接放入lib文件夹中就可以了。maven的话需要先上传到中央仓库去才能挂载。
然后新建一个工具类叫APKUtil,然后粘入如下代码:
import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import net.dongliu.apk.parser.ApkFile; import net.dongliu.apk.parser.bean.ApkMeta; import net.dongliu.apk.parser.bean.UseFeature; public class APKUtil { public static void main(String[] arg){ String filePath = "D:\\apk\\farmClient.apk"; try (ApkFile apkFile = new ApkFile(new File(filePath))) { ApkMeta apkMeta = apkFile.getApkMeta(); System.out.println(apkMeta.getName()); System.out.println(apkMeta.getPackageName()); System.out.println(apkMeta.getVersionCode()); System.out.println(apkMeta.getVersionName()); for (UseFeature feature : apkMeta.getUsesFeatures()) { System.out.println(feature.getName()); } } catch (IOException e) { e.printStackTrace(); } } /** * 获取APK信息-王啸-2018年4月18日13:05:52 * @param apkUrl * @return */ public static Map<String,Object> readApk(String apkUrl){ Map<String,Object> resMap=new HashMap<String,Object>(); try (ApkFile apkFile = new ApkFile(new File(apkUrl))) { ApkMeta apkMeta = apkFile.
最近在做行为识别,然后介绍一下目前种类多且数据量很大的行为数据集 Kinetics-600 dataset。
参考链接:
activityNet:http://activity-net.org/challenges/2018/index.html
GitHub:https://github.com/activitynet/ActivityNet
kinetics:https://deepmind.com/research/open-source/open-source-datasets/kinetics/
paper:https://arxiv.org/abs/1705.06950
1、背景与来源 目前activitynet第三届比赛已经开始了,这项比赛始于2016CVPR,是与ImageNet齐名的在视频理解方面最重要的比赛。
在这个比赛下的Task A – Trimmed Action Recognition比赛是一个视频分类比赛,数据集就是kinetics-600数据集。数据集有Google的deepmind团队提供,2017年是第一届比赛,当时有400个类别,20多万数据,今年又对数据集进行了扩增,现在有600个类别,共50万左右的视频。
2、介绍 视频来源于YouTube,一共有600个类别,每个类别至少600个视频以上,每段视频持续10秒左右。类别主要分为三大类:人与物互动,比如演奏乐器;人人互动,比如握手、拥抱;运动等。即person、person-person、person-object。
3、论文介绍 3.1 数据集类别介绍 下面这些介绍主要是参考于17年deepmind发的论文”The Kinetics Human Action Video Dataset”,当时还是400类的数据集。论文请见。
数据集主要关注人类行为,action类的列表包括:
单人行为,例如绘画,喝酒,大笑,抽拳;
人人行为,例如拥抱,亲吻,握手;
人物行为,例如打开礼物,修剪草坪,洗碗。
一些行动是比较细粒度的,需要时序推理来区分,例如,不同类型的游泳。其他动作类别需要强调区分对象,例如演奏不同类型的乐器。
这些类别并没有严格的层级划分,但是还是有些的,类似父类子类关系,例如音乐类(打鼓、长号、小提琴、……),个人卫生类(刷牙、剪指甲、洗手、……),跳舞类(芭蕾、macarena、tap、……),烹饪(切割、煎、脱皮、……)等。
数据集有400个类别,每个动作都有400-1150个视频片段,每段视频的时长都在10秒左右。目前的版本有306245视频,分为三个部分,训练时每个类为250-1000个视频,验证时每个类50个视频,测试时每个类100个视频。
每个类都包含了一种行动。但是,一个特定的剪辑可以包含 几种动作。例如,开车”时“发短信”;“弹奏尤克里里”时“跳草裙舞”;“跳舞”时“刷牙”。这种情况下,这个视频只会标记一个标签,并不会同时存在于两个类种。因此,取top-5的准确率更为合适。
3.2 Benchmark 一共验证了三种处理行为识别的主流模型,分别是LSTM、two stream和3dcnn。
放上准确率,可以看出two-stream还是占据主导优势的。在kinetics数据集上,top-1是61.0,top-5是81.3。
3.3 分类结果分析 上图是那些类分的比较好,那些类分的比较差。
还有一点,由于很多动作比较细粒度,类别之间容易造成混淆,论文中也给出了最容易混淆的几个类别,比如,跳远和三级跳远,吃汉堡和吃甜甜圈。swing跳舞和跳萨尔萨舞等都会混淆。
如下图:
当然,由于使用two stream模型,光流模型和RGB模型可能对不同的动作有不同的准确度,对于这些特定类别,可以在融合时对光流和RGB设定不同的权重。
上图中,对于机械舞,光流效果就会比RGB好很多,而对于做蛋糕,则是RGB效果更好。
3.4 粒度划分 最后给出这些类别的一个粒度划分,可能有多个类别都会属于同一大类。即父类子类关系。
首先列出有哪些父类,然后再给出每个父类下的子类。
3.4.1父类: 共38大类,每个类后面的数字代表有几个子类。
arts and crafts (12) athletics – jumping (6) athletics – throwing + launching (9) auto maintenance (4) ball sports (25) body motions (16) cleaning (13) cloths (8) communication (11) cooking (22) dancing (18) eating + drinking (17) electronics (5) garden + plants (10) golf (3) gymnastics (5) hair (14) hands (9) head + mouth (17) heights (15) interacting with animals (19) juggling (6) makeup (5) martial arts (10) miscellaneous (9) mobility – land (20) mobility – water (10) music (29) paper (12) personal hygiene (6) playing games (13) racquet + bat sports (8) snow + ice (18) swimming (3) touching person (11) using tools (13) water sports (8) waxing (4)
依赖 maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> .yml文件 配置mysql,jpa等 server: port: 8080 context-path: / helloWorld: spring Boot\u5927\u7237\u4F60\u597D msyql: jdbcName: com.mysql.jdbc.Driver dbUrl: jdbc:mysql://localhost:3306/wj33 userName: root password: spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/wj33?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: jpa: hibernate.ddl-auto: update show-sql: true database-platform: com.lunwen.wangjie.config.MySQL5DialectUTF8 thymeleaf: cache: false 实体类 实体类的注解 会根据注解自动生成表字段,@Table指定表名,不填,默认为类名@Column指定字段名,不填,默认为属性名其他注解指定字段的规则 import javax.persistence.*; @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; /** 姓名 */ @Column(name = "name") private String name; /** 密码 */ @Column(name = "
说到这几个关键字,大部分猿都能娓娓道来,说出很多它们的用法和定义
final修饰的字段不可修改、方法不可重写、类不可继承,JVM对final有优化static修饰的字段所有对象共用、static{}内的代码在类加载时执行、JVM对static有优化volatile修饰的字段所有线程看到的值一致 问:JVM对final和static有什么优化?
我:???
问:为什么volatile各线程看到的值是一致的?
我:嘿!这个我知道,因为对volatile的写操作会直接更新到主内存(这里指堆或元空间等线程共享内存)中,不会使用TLAB(这个在字节码上看不出来,也不在本文的讨论范围中。TLAB:Thread Local Allocation Buffer,本地线程分配缓冲)
带着这些疑问,我们一起看一下Java的字节码文件,从字节码文件中,就能印证和解决上述的部分说法和问题
static关键字
准备一个测试类
public class TestStatic { static double pi = 3.14; static Double piO = 3.14; static Object o1 = new Object(); Object o2 = new Object(); } 测试类很简单,四个字段都比较典型,在看字节码之前,先思考两个问题
pi和piO在编译后有区别吗?
答:JAVA有自动拆装箱,编译后可能没有区别...吧?o1和o2在编译后有区别吗?
答:o1是静态的,o2不是静态的(这不是废话么?) 可能大家都没有认真思考过这个问题,那么现在我们看一下TestStatic编译后的字节码文件,能否在其中找到答案
JDK提供了javap工具可以反编译字节码,使用如下命令可以方便的查看
javap -verbose F:\workspace\TestProject\out\production\TestProject\TestStatic.class
输出如下
Classfile /F:/workspace/TestProject/out/production/TestProject/TestStatic.class Last modified 2018-4-28; size 567 bytes MD5 checksum 73675b19fe69643d4cb69073bcbad34f Compiled from "TestStatic.java" public class TestStatic minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #2.