首页 文章 精选 留言 我的

精选列表

搜索[面试],共4948篇文章
优秀的个人博客,低调大师

SSM面试

Mybatis 简介 mybatis支持普通sql查询,存储过程和高级映射的优秀持久层框架,Mybatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检查,Mybatis使用简单的xml或注解用于配置和原始映射,将接口和Java的POJO(plan old Java Object)普通的Java对象映射成数据库的记录 每个mybatis应用程序主要都是使用SqlSessionFaction实例的,一个sqlSessionFaction实例可以通过sqlSessionFactionBuilder获得,SqlSessionFactionBuilder可以从一个xml配置文件或者一个预定义的配置类的实例获得 mybatis有一个实用类(Resources)它由很多方法,可以很方便地从类路径及其他位置加载资源 流程 加载配置并初始化 触发条件:加载配置文件 将sql的配置信息加载成为一个个mappedStatment对象,包括了传入参数映射 配置执行的sql语句,结果集映射配置,存储在内存中 接受调用请求 触发条件:调用mybatis提供的API 传入参数:为sql的id和传入参数对象 处理过程:将请求传递给下层的请求处理层进行处理 处理操作请求 触发条件:API接口层传递请求过来 传入参数:为sql的id和传入参数对象 处理过程: 根据sql的id查找对应的MappedStatment对象 根据传入参数对象解析MappedStatment对象,得到最终要执行的sql和执行传入的参数 获取数据连接,根据得到最终的sql语句和执行传入参数到数据库执行,并得到执行结果 根据MappedStatment对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果 释放连接资源 返回处理结果将最终的处理结果返回 功能架构(三层) API接口层: 提供给外部使用的接口API,开发人员通过本地API操作数据库,接口层接到调用请求,就会调用数据处理来完成具体的数据处理 数据处理层: 负责具体的sql查找、解析、执行和执行结果映射处理等,主要的目的是根据调用的请求完成一次数据库的操作 基础支持层 负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来做最基础的组件,为上层的数据处理层提供最基础的支撑 框架结构 加载配置 配置来源于两个地方: 1).配置文件中 2).Java代码的注解,将sql的配置信息加载为一个MappedStatment对象(包括传入参数映射配置,执行sql语句,结果映射配置)存储在内存中 sql解析 当API接口层接收到调用请求时,会接收到传入sql的id和传入对象(可以是map、JavaBean或基本类型),mybatis会根据sql的id找到对应的MappedStatment,然后传入参数对象的MappedStatment进行解析,解析后可以得到最终的要执行的sql语句和参数 sql执行 将最终得到的sql和参数拿到数据库进行执行,得到操作数据库的结果 结果映射 将操作数据库的结果按照映射的配置进行转换,可以转换成HashMap、JavaBean或者基本类型,并将最终结果返回 mybatis中#{}与${}的区别 ${} 是properties文件中的占位符,可用于标签属性值和sql内部,属于静态文本替换,比如${driver}会被静态替换为com.mysql.jdbc.Driver #{} 是sql的参数占位符,Mybatis会将sql中的#{}替换为?,在sql执行前会使用preparedStatement的参数设置方法,按序给sql的?占位符设置参数值,比如ps.setInt(0,ParameterValue),#{item.name}的取值方式为使用反射从参数对象中获取item对象的name属性值,相当于param.getItem().getName()。 XML映射文件中,除了常见的select、insert、update、delete标签之外,还有哪些标签 <resultMap>返回值类型、<sql>、<include>、<selectKey>加上动态sql的9个标签(trim、where、set、foreach、if、choose、when、otherwise、bind)其中<sql>为sql片段标签,通过<include>标签引入sql片段,<selectKey>为不支持自增的主键生产策略标签 一个XML文件都会写一个Dao接口与之对应,工作原理 Dao接口,常说的mapper接口,接口的权限名就是映射文件中的namespace的值,接口的方法名,就是映射文件MappedStatment的id值,接口方法的参数就是传递给slq的参数,mapper接口是没有实现类的,当调用接口方法时,接口权限名+方法名拼接字符串作为key值,可唯一定位一个mappedStatmentDao接口里的方法是不能重载的,因为是权限名+方法名的保存和寻找策略 Mybatis是如何分页的 mybatis是使用RowBounds对象进行分页的,针对ResultSet结果集进行的内存分页而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页的功能 springMVC 是一个mvc框架,在web模型中,mvc是一种很流行的框架,通过把model、view、controller分离,把较为复杂的web应用分成逻辑清晰的几部分,是为了简化开发,减少出错,或是为了组内开发人员之间的配,总之就是一种分层工作的办法 是spring的一个子框架,当然拥有spring的特性,如依赖注入,注解:RequestMapping,专门负责映射的url spring是什么 spring是开源的轻量级的开发应用框架,目的是用于简化企业级应用程序开发 原理 通过配置方式来创建对象,管理对象之间依赖关系,我们不需要通过工厂和生成器来创建及管理对象之间的依赖关系,这样我们是不是减少了许多工作,加速了开发 spring框架除了帮助我们管理对象及其依赖关系,还提供了日志记录、性能统计、安全控制、异常处理等面向切面的能力,还能帮我们管理最头疼的数据库事务,本身提供了一套简单的JDBC访问实现,提供与第三方数据访问框架集成(如Hibernate、JPA)与各种javaEE技术整合,提供一套自己的web层框架springMVC,而且还能非常简单的与第三方web框架集成 作用 能帮助我们根据配置文件创建及组装对象之间的依赖关系(无需重新编译,只需要修改配置文件) spring提供了与第三方数据访问框架无缝集成,而且自己提供了一套JDBC/springMVC框架,方便数据库/web层搭建(第三方web【如struts、JSF】) 为什么需要spring 应用程序 是能完成我们所需的功能的成品,比如:购物网站、OA系统 框架 是能够完成功能的半产品,框架规定了开发过程中的整体架构,提供了基础功能 非侵入式设计 从框架角度可以理解为,无需继承框架提供的类 POJO(plan old java Object)简单的Java对象 它可以包含业务逻辑或持久化逻辑,但不担当任何特殊角色且不继承或不实现任何其他java框架的类或接口 轻量级及重量级 轻量级是相对于重量级而言的,轻量级一般是非入侵性的,所依赖的东西非常少,资源占用非常少,部署简单,极易使用,重量级相反 容器 装对象的对象,因为存在放入、拿出等操作,所以容器还要管理对象的生命周期 控制反转 即Inversion of Control(IOC)/ 依赖注入(Dependency Injection),即由容器控制程序之间的关系,而非由程序直接操控 Bean 一般指容器管理对象,在spring中指springIOC容器管理对象 为什么使用spring 能帮助我们简化应用程序开发,帮助我们创建和组装对象,为我们管理事务,简单的mvc框架,可以把spring看作是一个超级粘合平台,能够把很多技术整合在一起,形成一个整体,使系统结构更出众,更优秀,从而加速我们程序开发 Spring的BeanFactory和ApplicationContext的区别 spring使用BeanFactory来实例化配置和管理对象,但是它只是一个接口,里面有一个getBean()方法,我们一般都不直接用BeanFactory,而是用它的实现类ApplicationContext,这个类会自动解析我们配置的applicationContext.xml,然后根据我们配置的bean来new对象,将new好的对象放进一个Map中,键就是我们bean的id,值就是new的对象BeanFactory是spring中比较原始的Factory,如XMLBeanFactory就是一种典型的BeanFactory,原始的BeanFactory无法支持spring的许多插件,例如:AOP、web应用等ApplicationContext接口,它由BeanFactory接口派生而来,因而提供BeanFactory所有的功能 容器是spring的核心 BeanFactory 是spring中比较原始的Factory,如XMLBeanFactory就是一种典型的BeanFactory,原始的BeanFactory无法支持spring的许多插件,例如:AOP、web应用等 ApplicationContext 三个实现类 classPathXMLApplication:把上下文文件当成类路径资源 FileSystemXMLApplication:从文件系统中的XML文件载入上下文定义信息 XMLWebApplicationContext:从web系统中的XML文件载入上下文定义信息 作用 BeanFactory负责读取Bean配置文档,管理Bean的加载,实例化,维护Bean之间的依赖关系,负责Bean的生命周期 ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能 a. 国际化支持 b. 资源访问 c. 时间传递(通过实现ApplicationContextAware接口) 常用的获取ApplicationContext的方法 FileSystemXMLApplicationConrext 从文件系统或者url指定的xml配置文件创建参数为配置文件名或文件名数组。 classPathXMLApplicationContext 从classPath的xml配置文件创建,可以从jar包中读取配置文件

优秀的个人博客,低调大师

Java面试

1、java事件机制包括哪三个部分?分别介绍。 2、为什么要使用线程池? 3、线程池有什么作用? 4、说说几种常见的线程池及使用场景。 5、线程池都有哪几种工作队列? 6、怎么理解无界队列和有界队列? 7、线程池中的几种重要的参数及流程说明。 8、什么是反射机制? 9、说说反射机制的作用。 10、反射机制会不会有性能问题? 11、你怎么理解http协议? 12、说说http协议的工作流程。 13、http有哪些请求提交方式? 14、http中的200,302,403,404,500,503都代表什么状态? 15、http get和post有什么区别? 16、你怎么理解cookie和session,有哪些不同点? 17、什么是web缓存?有什么优点? 18、什么是https,说说https的工作原理? 19、什么是http代理服务器,有什么用? 20、什么是虚拟主机及实现原理? 21、什么是Java虚拟机,为什么要使用? 22、说说Java虚拟机的生命周期及体系结构。 23、说一说Java内存区域。 24、什么是分布式系统? 25、分布式系统你会考虑哪些方面? 26、讲一讲TCP协议的三次握手和四次挥手流程。 27、为什么TCP建立连接协议是三次握手,而关闭连接却是四次握手呢?为什么不能用两次握手进行连接? 28、为什么TCP TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态? 29、什么是DoS、DDoS、DRDoS攻击?如何防御? 30、描述一下Java异常层次结构。 31、什么是检查异常,不受检查异常,运行时异常?并分别举例说明。 32、finally块一定会执行吗? 33、正常情况下,当在try块或catch块中遇到return语句时,finally语句块在方法返回之前还是之后被执行? 34、try、catch、finally语句块的执行顺序。 35、Java虚拟机中,数据类型可以分为哪几类? 36、怎么理解栈、堆?堆中存什么?栈中存什么? 37、为什么要把堆和栈区分出来呢?栈中不是也可以存储数据吗? 38、在Java中,什么是是栈的起始点,同是也是程序的起始点? 39、为什么不把基本类型放堆中呢? 40、Java中的参数传递时传值呢?还是传引用? 41、Java中有没有指针的概念? 42、Java中,栈的大小通过什么参数来设置? 43、一个空Object对象的占多大空间? 44、对象引用类型分为哪几类? 45、讲一讲垃圾回收算法。 46、如何解决内存碎片的问题? 47、如何解决同时存在的对象创建和对象回收问题? 48、讲一讲内存分代及生命周期。 49、什么情况下触发垃圾回收? 50、如何选择合适的垃圾收集算法? 51、JVM中最大堆大小有没有限制? 52、堆大小通过什么参数设置? 53、JVM有哪三种垃圾回收器? 54、吞吐量优先选择什么垃圾回收器?响应时间优先呢? 55、如何进行JVM调优?有哪些方法? 56、如何理解内存泄漏问题?有哪些情况会导致内存泄露?如何解决? 57、从分布式系统部署角度考虑,分哪几层? 58、如何解决业务层的数据访问问题? 59、为了解决数据库服务器的负担,如何做数据库的分布? 60、什么是著名的拜占庭将军问题? 61、为什么说TCP/IP协议是不可靠的? 62、讲讲CAP理念。 63、怎么理解强一致性、单调一致性和最终一致性? 64、分布式系统设计你会考虑哪些策略? 65、最常见的数据分布方式是什么? 66、谈一谈一致性哈希算法。 67、paxos是什么? 68、什么是Lease机制? 69、如何理解选主算法? 70、OSI有哪七层模型?TCP/IP是哪四层模型。

优秀的个人博客,低调大师

面试准备

想去名企锻炼自己的技术本领,梳理一下技术的要求,做好准备,希望能达成自己的目标。 Java基础扎实,理解IO,多线程,集合等基础框架,对JVM有一定的了解。 前天一位Java大牛告诉我,刚毕业一年最好还是准备基础,刚毕业一年没有大型的项目经验,基础就要足够的耐问。 对使用的开源框架,能了解到他的原理和机制,对Spring,Mybatis等开源框架熟悉。 Spring,Mybatis系列的开源框架,研读源码...一定要能说自己精通Spring,Mybatis。做到如此才有希望。 熟悉分布式系统的设计和应用,熟悉分布式,缓存,消息等机制,能对分布式常用技术进行合理应用解决问题。 分布式的毕竟也做过一些,但要有自己的思考... 熟悉Linux操作系统,和大型数据库(Oracle,MySQL),对常见的NoSQL(Redis,MongoDB,HBase,Memcached)有一点研究。 追求并尝试最新的技术,追求编码的优雅,从技术趋势和思路上能影响团队,学习能力好,适应能力强,具备耐心,细心的品质。 刷名企Offer这本书,熟悉Tcp/ip协议,数据结构和算法。 最后 我能准备的差不多就以上的内容了,干!

优秀的个人博客,低调大师

Spark面试

1、简答说一下hadoop的map-reduce编程模型 首先map task会从本地文件系统读取数据,转换成key-value形式的键值对集合 使用的是hadoop内置的数据类型,比如longwritable、text等 将键值对集合输入mapper进行业务处理过程,将其转换成需要的key-value在输出 之后会进行一个partition分区操作,默认使用的是hashpartitioner,可以通过重写hashpartitioner的getpartition方法来自定义分区规则 之后会对key进行进行sort排序,grouping分组操作将相同key的value合并分组输出,在这里可以使用自定义的数据类型,重写WritableComparator的Comparator方法来自定义排序规则,重写RawComparator的compara方法来自定义分组规则 之后进行一个combiner归约操作,其实就是一个本地段的reduce预处理,以减小后面shufle和reducer的工作量 reduce task会通过网络将各个数据收集进行reduce处理,最后将数据保存或者显示,结束整个job 2、hadoop的TextInputFormat作用是什么,如何自定义实现 InputFormat会在map操作之前对数据进行两方面的预处理 1是getSplits,返回的是InputSplit数组,对数据进行split分片,每片交给map操作一次 2是getRecordReader,返回的是RecordReader对象,对每个split分片进行转换为key-value键值对格式传递给map 常用的InputFormat是TextInputFormat,使用的是LineRecordReader对每个分片进行键值对的转换,以行偏移量作为键,行内容作为值 自定义类继承InputFormat接口,重写createRecordReader和isSplitable方法 在createRecordReader中可以自定义分隔符 3、hadoop和spark的都是并行计算,那么他们有什么相同和区别 两者都是用mr模型来进行并行计算,hadoop的一个作业称为job,job里面分为map task和reduce task,每个task都是在自己的进程中运行的,当task结束时,进程也会结束 spark用户提交的任务成为application,一个application对应一个sparkcontext,app中存在多个job,每触发一次action操作就会产生一个job 这些job可以并行或串行执行,每个job中有多个stage,stage是shuffle过程中DAGSchaduler通过RDD之间的依赖关系划分job而来的,每个stage里面有多个task,组成taskset有TaskSchaduler分发到各个executor中执行,executor的生命周期是和app一样的,即使没有job运行也是存在的,所以task可以快速启动读取内存进行计算 hadoop的job只有map和reduce操作,表达能力比较欠缺而且在mr过程中会重复的读写hdfs,造成大量的io操作,多个job需要自己管理关系 spark的迭代计算都是在内存中进行的,API中提供了大量的RDD操作如join,groupby等,而且通过DAG图可以实现良好的容错 4、为什么要用flume导入hdfs,hdfs的构架是怎样的 flume可以实时的导入数据到hdfs中,当hdfs上的文件达到一个指定大小的时候会形成一个文件,或者超过指定时间的话也形成一个文件 文件都是存储在datanode上面的,namenode记录着datanode的元数据信息,而namenode的元数据信息是存在内存中的,所以当文件切片很小或者很多的时候会卡死 5、map-reduce程序运行的时候会有什么比较常见的问题 比如说作业中大部分都完成了,但是总有几个reduce一直在运行 这是因为这几个reduce中的处理的数据要远远大于其他的reduce,可能是因为对键值对任务划分的不均匀造成的数据倾斜 解决的方法可以在分区的时候重新定义分区规则对于value数据很多的key可以进行拆分、均匀打散等处理,或者是在map端的combiner中进行数据预处理的操作 6、简单说一下hadoop和spark的shuffle过程 hadoop:map端保存分片数据,通过网络收集到reduce端 spark:spark的shuffle是在DAGSchedular划分Stage的时候产生的,TaskSchedule要分发Stage到各个worker的executor 减少shuffle可以提高性能 7、Hive中存放是什么? 表。 存的是和hdfs的映射关系,hive是逻辑上的数据仓库,实际操作的都是hdfs上的文件,HQL就是用sql语法来写的mr程序。 8、Hive与关系型数据库的关系? 没有关系,hive是数据仓库,不能和数据库一样进行实时的CURD操作。 是一次写入多次读取的操作,可以看成是ETL工具。 9、Flume工作机制是什么? 核心概念是agent,里面包括source、chanel和sink三个组件。 source运行在日志收集节点进行日志采集,之后临时存储在chanel中,sink负责将chanel中的数据发送到目的地。 只有成功发送之后chanel中的数据才会被删除。 首先书写flume配置文件,定义agent、source、chanel和sink然后将其组装,执行flume-ng命令。 10、Sqoop工作原理是什么? hadoop生态圈上的数据传输工具。 可以将关系型数据库的数据导入非结构化的hdfs、hive或者bbase中,也可以将hdfs中的数据导出到关系型数据库或者文本文件中。 使用的是mr程序来执行任务,使用jdbc和关系型数据库进行交互。 import原理:通过指定的分隔符进行数据切分,将分片传入各个map中,在map任务中在每行数据进行写入处理没有reduce。 export原理:根据要操作的表名生成一个java类,并读取其元数据信息和分隔符对非结构化的数据进行匹配,多个map作业同时执行写入关系型数据库 11、Hbase行健列族的概念,物理模型,表的设计原则? 行健:是hbase表自带的,每个行健对应一条数据。 列族:是创建表时指定的,为列的集合,每个列族作为一个文件单独存储,存储的数据都是字节数组,其中的数据可以有很多,通过时间戳来区分。 物理模型:整个hbase表会拆分为多个region,每个region记录着行健的起始点保存在不同的节点上,查询时就是对各个节点的并行查询,当region很大时使用.META表存储各个region的起始点,-ROOT又可以存储.META的起始点。 rowkey的设计原则:各个列簇数据平衡,长度原则、相邻原则,创建表的时候设置表放入regionserver缓存中,避免自动增长和时间,使用字节数组代替string,最大长度64kb,最好16字节以内,按天分表,两个字节散列,四个字节存储时分毫秒。 列族的设计原则:尽可能少(按照列族进行存储,按照region进行读取,不必要的io操作),经常和不经常使用的两类数据放入不同列族中,列族名字尽可能短。 12、Spark Streaming和Storm有何区别? 一个实时毫秒一个准实时亚秒,不过storm的吞吐率比较低。 13、mllib支持的算法? 大体分为四大类,分类、聚类、回归、协同过滤。 14、简答说一下hadoop的map-reduce编程模型? 首先map task会从本地文件系统读取数据,转换成key-value形式的键值对集合。 将键值对集合输入mapper进行业务处理过程,将其转换成需要的key-value在输出。 之后会进行一个partition分区操作,默认使用的是hashpartitioner,可以通过重写hashpartitioner的getpartition方法来自定义分区规则。 之后会对key进行进行sort排序,grouping分组操作将相同key的value合并分组输出。 在这里可以使用自定义的数据类型,重写WritableComparator的Comparator方法来自定义排序规则,重写RawComparator的compara方法来自定义分组规则。 之后进行一个combiner归约操作,其实就是一个本地段的reduce预处理,以减小后面shufle和reducer的工作量。 reduce task会通过网络将各个数据收集进行reduce处理,最后将数据保存或者显示,结束整个job。 15、Hadoop平台集群配置、环境变量设置? zookeeper:修改zoo.cfg文件,配置dataDir,和各个zk节点的server地址端口,tickTime心跳时间默认是2000ms,其他超时的时间都是以这个为基础的整数倍,之后再dataDir对应目录下写入myid文件和zoo.cfg中的server相对应。 hadoop:修改 hadoop-env.sh配置java环境变量 core-site.xml配置zk地址,临时目录等 hdfs-site.xml配置nn信息,rpc和http通信地址,nn自动切换、zk连接超时时间等 yarn-site.xml配置resourcemanager地址 mapred-site.xml配置使用yarn slaves配置节点信息 格式化nn和zk。 hbase:修改 hbase-env.sh配置java环境变量和是否使用自带的zk hbase-site.xml配置hdfs上数据存放路径,zk地址和通讯超时时间、master节点 regionservers配置各个region节点 zoo.cfg拷贝到conf目录下 spark: 安装Scala 修改spark-env.sh配置环境变量和master和worker节点配置信息 环境变量的设置:直接在/etc/profile中配置安装的路径即可,或者在当前用户的宿主目录下,配置在.bashrc文件中,该文件不用source重新打开shell窗口即可,配置在.bash_profile的话只对当前用户有效。 16、Hadoop性能调优? 调优可以通过系统配置、程序编写和作业调度算法来进行。 hdfs的block.size可以调到128/256(网络很好的情况下,默认为64) 调优的大头:mapred.map.tasks、mapred.reduce.tasks设置mr任务数(默认都是1) mapred.tasktracker.map.tasks.maximum每台机器上的最大map任务数 mapred.tasktracker.reduce.tasks.maximum每台机器上的最大reduce任务数 mapred.reduce.slowstart.completed.maps配置reduce任务在map任务完成到百分之几的时候开始进入 这个几个参数要看实际节点的情况进行配置,reduce任务是在33%的时候完成copy,要在这之前完成map任务,(map可以提前完成) mapred.compress.map.output,mapred.output.compress配置压缩项,消耗cpu提升网络和磁盘io 合理利用combiner 注意重用writable对象 17、Hadoop高并发? 首先肯定要保证集群的高可靠性,在高并发的情况下不会挂掉,支撑不住可以通过横向扩展。 datanode挂掉了使用hadoop脚本重新启动。 18、hadoop的TextInputFormat作用是什么,如何自定义实现? InputFormat会在map操作之前对数据进行两方面的预处理。 1是getSplits,返回的是InputSplit数组,对数据进行split分片,每片交给map操作一次 。 2是getRecordReader,返回的是RecordReader对象,对每个split分片进行转换为key-value键值对格式传递给map。 常用的InputFormat是TextInputFormat,使用的是LineRecordReader对每个分片进行键值对的转换,以行偏移量作为键,行内容作为值。 自定义类继承InputFormat接口,重写createRecordReader和isSplitable方法 。 在createRecordReader中可以自定义分隔符。 19、hadoop和spark的都是并行计算,那么他们有什么相同和区别? 两者都是用mr模型来进行并行计算,hadoop的一个作业称为job,job里面分为map task和reduce task,每个task都是在自己的进程中运行的,当task结束时,进程也会结束。 spark用户提交的任务成为application,一个application对应一个sparkcontext,app中存在多个job,每触发一次action操作就会产生一个job。 这些job可以并行或串行执行,每个job中有多个stage,stage是shuffle过程中DAGSchaduler通过RDD之间的依赖关系划分job而来的,每个stage里面有多个task,组成taskset有TaskSchaduler分发到各个executor中执行,executor的生命周期是和app一样的,即使没有job运行也是存在的,所以task可以快速启动读取内存进行计算。 hadoop的job只有map和reduce操作,表达能力比较欠缺而且在mr过程中会重复的读写hdfs,造成大量的io操作,多个job需要自己管理关系。 spark的迭代计算都是在内存中进行的,API中提供了大量的RDD操作如join,groupby等,而且通过DAG图可以实现良好的容错。 20、为什么要用flume导入hdfs,hdfs的构架是怎样的? flume可以实时的导入数据到hdfs中,当hdfs上的文件达到一个指定大小的时候会形成一个文件,或者超过指定时间的话也形成一个文件。 文件都是存储在datanode上面的,namenode记录着datanode的元数据信息,而namenode的元数据信息是存在内存中的,所以当文件切片很小或者很多的时候会卡死。 21、map-reduce程序运行的时候会有什么比较常见的问题? 比如说作业中大部分都完成了,但是总有几个reduce一直在运行。 这是因为这几个reduce中的处理的数据要远远大于其他的reduce,可能是因为对键值对任务划分的不均匀造成的数据倾斜。 解决的方法可以在分区的时候重新定义分区规则对于value数据很多的key可以进行拆分、均匀打散等处理,或者是在map端的combiner中进行数据预处理的操作。 22、简单说一下hadoop和spark的shuffle过程? hadoop:map端保存分片数据,通过网络收集到reduce端。 spark:spark的shuffle是在DAGSchedular划分Stage的时候产生的,TaskSchedule要分发Stage到各个worker的executor。 减少shuffle可以提高性能。 23、RDD机制? rdd分布式弹性数据集,简单的理解成一种数据结构,是spark框架上的通用货币。 所有算子都是基于rdd来执行的,不同的场景会有不同的rdd实现类,但是都可以进行互相转换。 rdd执行过程中会形成dag图,然后形成lineage保证容错性等。 从物理的角度来看rdd存储的是block和node之间的映射。 24、spark有哪些组件? (1)master:管理集群和节点,不参与计算。 (2)worker:计算节点,进程本身不参与计算,和master汇报。 (3)Driver:运行程序的main方法,创建spark context对象。 (4)spark context:控制整个application的生命周期,包括dagsheduler和task scheduler等组件。 (5)client:用户提交程序的入口。 25、spark工作机制? 用户在client端提交作业后,会由Driver运行main方法并创建spark context上下文。 执行add算子,形成dag图输入dagscheduler,按照add之间的依赖关系划分stage输入task scheduler。 task scheduler会将stage划分为task set分发到各个节点的executor中执行。 26、spark的优化怎么做? 通过spark-env文件、程序中sparkconf和set property设置。 (1)计算量大,形成的lineage过大应该给已经缓存了的rdd添加checkpoint,以减少容错带来的开销。 (2)小分区合并,过小的分区造成过多的切换任务开销,使用repartition。 27、kafka工作原理? producer向broker发送事件,consumer从broker消费事件。 事件由topic区分开,每个consumer都会属于一个group。 相同group中的consumer不能重复消费事件,而同一事件将会发送给每个不同group的consumer。 28、ALS算法原理? 答:对于user-product-rating数据,als会建立一个稀疏的评分矩阵,其目的就是通过一定的规则填满这个稀疏矩阵。 als会对稀疏矩阵进行分解,分为用户-特征值,产品-特征值,一个用户对一个产品的评分可以由这两个矩阵相乘得到。 通过固定一个未知的特征值,计算另外一个特征值,然后交替反复进行最小二乘法,直至差平方和最小,即可得想要的矩阵。 29、kmeans算法原理? 随机初始化中心点范围,计算各个类别的平均值得到新的中心点。 重新计算各个点到中心值的距离划分,再次计算平均值得到新的中心点,直至各个类别数据平均值无变化。 30、canopy算法原理? 根据两个阈值来划分数据,以随机的一个数据点作为canopy中心。 计算其他数据点到其的距离,划入t1、t2中,划入t2的从数据集中删除,划入t1的其他数据点继续计算,直至数据集中无数据。 31、朴素贝叶斯分类算法原理? 对于待分类的数据和分类项,根据待分类数据的各个特征属性,出现在各个分类项中的概率判断该数据是属于哪个类别的。 32、关联规则挖掘算法apriori原理? 一个频繁项集的子集也是频繁项集,针对数据得出每个产品的支持数列表,过滤支持数小于预设值的项,对剩下的项进行全排列,重新计算支持数,再次过滤,重复至全排列结束,可得到频繁项和对应的支持数。

优秀的个人博客,低调大师

面试2

JAVA 相关 1.静态内部类、内部类、匿名内部类,为什么内部类会持有外部类的引用?持有的引用是this?还是其它? 静态内部类:使用static修饰的内部类 内部类:就是在某个类的内部又定义了一个类,内部类所嵌入的类称为外部类 匿名内部类:使用new生成的内部类 因为内部类的产生依赖于外部类,持有的引用是类名.this 2.Java中try catch finally的执行顺序 先执行try中代码,如果发生异常执行catch中代码,最后一定会执行finally中代码 3.equals与==的区别: ==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相 4.Object有哪些公用方法? 方法equals测试的是两个对象是否相等 方法clone进行对象拷贝 方法getClass返回和当前对象相关的Class对象 方法notify,notifyall,wait都是用来对给定对象进行线程同步的 5.String、StringBuffer与StringBuilder的区别 String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象 StringBuffer和StringBuilder底层是 char[]数组实现的 StringBuffer是线程安全的,而StringBuilder是线程不安全的 6.Java的四种引用的区别 强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM 也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象 软引用:在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用才会被垃圾回收器回收。 弱引用:具有弱引用的对象拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象 虚引用:顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。 7.介绍垃圾回收机制 标记回收法:遍历对象图并且记录可到达的对象,以便删除不可到达的对象,一般使用单线程工作并且可能产生内存碎片 标记-压缩回收法:前期与第一种方法相同,只是多了一步,将所有的存活对象压缩到内存的一端,这样内存碎片就可以合成一大块可再利用的内存区域,提高了内存利用率 复制回收法:把现有内存空间分成两部分,gc运行时,它把可到达对象复制到另一半空间,再清空正在使用的空间的全部对象。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。 分代回收发:把内存空间分为两个或者多个域,如年轻代和老年代,年轻代的特点是对象会很快被回收,因此在年轻代使用效率比较高的算法。当一个对象经过几次回收后依然存活,对象就会被放入称为老年的内存空间,老年代则采取标记-压缩算法 集合、数据结构相关 1.你用过哪些集合类 数据结构中用于存储数据的有哪些 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大。但数组的二分查找时间复杂度小,为O(1);数组的特点是:寻址容易,插入和删除困难; 链表 链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。链表的特点是:寻址困难,插入和删除容易。 2.说说hashMap是怎样实现的 哈希表:由数组+链表组成的 当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。 3.ArrayList,LinkedList的区别 ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 4.ArrayList和Vector的主要区别是什么? ArrayList 和Vector底层是采用数组方式存储数据 Vector: 线程同步 当Vector中的元素超过它的初始大小时,Vector会将它的容量翻倍, ArrayList: 线程不同步,但性能很好 当ArrayList中的元素超过它的初始大小时,ArrayList只增加50%的大小 5.HashMap和 HashTable 的区别: HashTable比较老,是基于Dictionary 类实现的,HashTable 则是基于 Map接口实现的 HashTable 是线程安全的, HashMap 则是线程不安全的 HashMap可以让你将空值作为一个表的条目的key或value 算法相关 1.排序算法和稳定性,快排什么时候情况最坏? 2.给最外层的rootview,把这个根视图下的全部button背景设置成红色,手写代码,不许用递归 算法原理: Android的view视图是按树形结构分布,所以按树形结构遍历 循环判断每一层的ViewGroup元素,将其入栈;否则判断当前view是否是Button类实例,是则改写背景色 当前ViewGroup检查childView完成后,判断栈是否非空,取出栈顶元素ViewGroup重复步骤2直至栈为空。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void changeAllBtnBGColor(View view, int color) { if (view == null || !(view instanceof ViewGroup)) return ; Stack m = new Stack<>(); while (view != null ) { ViewGroup tmpGroup = (ViewGroup) view; int count = tmpGroup.getChildCount(); for ( int i = 0 ; i < count; i++) { View child = tmpGroup.getChildAt(i); if (child instanceof ViewGroup) m.add(child); else if (child instanceof Button) { child.setBackgroundColor(color); } } if (m.isEmpty()) break ; else view = m.pop(); } } Thread、AsynTask相关 1.wait()和sleep()的区别 sleep来自Thread类,和wait来自Object类 调用sleep()方法的过程中,线程不会释放对象锁。而 调用 wait 方法线程会释放对象锁 sleep睡眠后不出让系统资源,wait让出系统资源其他线程可以占用CPU sleep(milliseconds)需要指定一个睡眠时间,时间一到会自动唤醒 2.若Activity已经销毁,此时AsynTask执行完并且返回结果,会报异常吗? 当一个App旋转时,整个Activity会被销毁和重建。当Activity重启时,AsyncTask中对该Activity的引用是无效的,因此onPostExecute()就不会起作用,若AsynTask正在执行,折会报 view not attached to window manager 异常 同样也是生命周期的问题,在 Activity 的onDestory()方法中调用Asyntask.cancal方法,让二者的生命周期同步 3.Activity销毁但Task如果没有销毁掉,当Activity重启时这个AsyncTask该如何解决? 还是屏幕旋转这个例子,在重建Activity的时候,会回掉Activity.onRetainNonConfigurationInstance()重新传递一个新的对象给AsyncTask,完成引用的更新 4.Android 线程间通信有哪几种方式(重要) 共享内存(变量); 文件,数据库; Handler; Java 里的 wait(),notify(),notifyAll() 5.请介绍下 AsyncTask的内部实现,适用的场景是 AsyncTask 内部也是 Handler 机制来完成的,只不过 Android 提供了执行框架来提供线程池来 执行相应地任务,因为线程池的大小问题,所以 AsyncTask 只应该用来执行耗时时间较短的任务, 比如 HTTP 请求,大规模的下载和数据库的更改不适用于 AsyncTask,因为会导致线程池堵塞,没有 线程来执行其他的任务,导致的情形是会发生 AsyncTask 根本执行不了的问题。 网络相关 1.TCP三次握手 2.为什么TCP是可靠的,UDP早不可靠的?为什么UDP比TCP快? TCP/IP协议高,因为其拥有三次握手双向机制,这一机制保证校验了数据,保证了他的可靠性。 UDP就没有了,udp信息发出后,不验证是否到达对方,所以不可靠。 但是就速度来说,还是UDP协议更高,毕竟其无需重复返回验证,只是一次性的 3.http协议了解多少,说说里面的协议头部有哪些字段? http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议;http请求由三部分组成,分别是:请求行、消息报头、请求正文。 HTTP消息报头包括普通报头、请求报头、响应报头、实体报头 4.https了解多少 HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 5.谈谈 HTTP 中Get 和 Post 方法的区别 GET - 从指定的服务器中获取数据,明文发送内容 POST - 提交数据给指定的服务器处理 1. POST请求不能被缓存下来 2. POST请求不会保存在浏览器浏览记录中 3. 以POST请求的URL无法保存为浏览器书签 4. POST请求没有长度限制 6.推送心跳包是TCP包还是UDP包或者HTTP包 心跳包的实现是调用了socket.sendUrgentData(0xFF)这句代码实现的,所以,当然是TCP包。 7.如何实现文件断点上传 在 Android 中上传文件可以采用 HTTP 方式,也可以采用 Socket 方式,但是 HTTP 方式不能上传 大文件,这里介绍一种通过 Socket 方式来进行断点续传的方式,服务端会记录下文件的上传进度, 当某一次上传过程意外终止后,下一次可以继续上传,这里用到的其实还是 J2SE 里的知识。 这个上传程序的原理是:客户端第一次上传时向服务端发送 “Content-Length=35;filename=WinRAR_3.90_SC.exe;sourceid=“这种格式的字符串,服务端 收到后会查找该文件是否有上传记录,如果有就返回已经上传的位置,否则返回新生成的 sourceid 以及 position 为 0,类似 sourceid=2324838389;position=0“这样的字符串,客户端收到返回后 的字符串后再从指定的位置开始上传文件。 Fragment相关 1.Fragment 如何实现类似 Activity 栈的压栈和出栈效果的? Fragment 的事物管理器内部维持了一个双向链表结构,该结构可以记录我们每次 add 的 Fragment 和 replace 的 Fragment,然后当我们点击 back 按钮的时候会自动帮我们实现退栈操作。 2.Fragment 在你们项目中的使用 Fragment 是 android3.0 以后引入的的概念,做局部内容更新更方便,原来为了到达这一点要 把多个布局放到一个 activity 里面,现在可以用多 Fragment 来代替,只有在需要的时候才加载 Fragment,提高性能。 Fragment 的好处: 1. Fragment 可以使你能够将 activity 分离成多个可重用的组件,每个都有它自己的生命周期和 UI。 2. Fragment 可以轻松得创建动态灵活的 UI 设计,可以适应于不同的屏幕尺寸。从手机到平板电 脑。 3. Fragment 是一个独立的模块,紧紧地与 activity 绑定在一起。可以运行中动态地移除、加入、 交换等。 4. Fragment 提供一个新的方式让你在不同的安卓设备上统一你的 UI。 5. Fragment 解决 Activity 间的切换不流畅,轻量切换。 6. Fragment 替代 TabActivity 做导航,性能更好。 7. Fragment 在 4.2.版本中新增嵌套 fragment 使用方法,能够生成更好的界面效果 3.如何切换 fragement,不重新实例化 正确的切换方式是 add(),切换时 hide(),add()另一个 Fragment;再次切换时,只需 hide()当前, show()另一个 四大组件相关 1.Activity和Fragment生命周期有哪些? Activity——onCreate->onStart->onResume->onPause->onStop->onDestroy Fragment——onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume->onPause->onStop->onDestroyView->onDestroy->onDetach 2.广播的两种注册方式及有什么区别 3.内存不足时,怎么保持Activity的一些状态,在哪个方法里面做具体操作? Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。除非该activity是被用户主动销毁的,通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。 4.启动service的两种方法?有什么区别? 一种是startService(),另一种是bindService()。这两者的区别是第一种方式调用者开启了服务,即会与服务失去联系,两者没有关联。即使访问者退出了,服务仍在运行。如需解除服务必须显式的调用stopService方法。主要用于调用者与服务没有交互的情况下,也就是调用者不需要获取服务里的业务方法。比如电话录音。而后者调用者与服务绑定在一起的。当调用者退出的时候,服务也随之退出。用于需要与服务交互。 5.Android中的Context, Activity,Appliction有什么区别? 相同:Activity和Application都是Context的子类。 Context从字面上理解就是上下文的意思,在实际应用中它也确实是起到了管理上下文环境中各个参数和变量的总用,方便我们可以简单的访问到各种资源。 不同:维护的生命周期不同。 Context维护的是当前的Activity的生命周期,Application维护的是整个项目的生命周期。 使用context的时候,小心内存泄露,防止内存泄露,注意一下几个方面: 1. 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的。 2. 对于生命周期长的对象,可以使用application,context。 3. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化。 6.Context是什么? 它描述的是一个应用程序环境的信息,即上下文。 该类是一个抽象(abstract class)类,Android提供了该抽象类的具体实现类(ContextIml)。 通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Intent,信息,等。 7.Service 是否在 main thread 中执行, service 里面是否能执行耗时的操 作? 默认情况,如果没有显示的指 servic 所运行的进程, Service 和 activity 是运行在当前 app 所在进 程的 main thread(UI 主线程)里面。 service 里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 ) 特殊情况 ,可以在清单文件配置 service 执行所在的进程 ,让 service 在另外的进程中执行 1 2 3 4 5 <service android:name= "com.baidu.location.f" android:enabled= "true" android:process= ":remote" > </service> 8.Activity 怎么和 Service 绑定,怎么在 Activity 中启动自己对应的 Service? Activity 通过 bindService(Intent service, ServiceConnection conn, int flags)跟 Service 进行 绑定,当绑定成功的时候 Service 会将代理对象通过回调的形式传给 conn,这样我们就拿到了 Service 提供的服务代理对象。 在 Activity 中可以通过 startService 和 bindService 方法启动 Service。一般情况下如果想获取 Service 的服务对象那么肯定需要通过 bindService()方法,比如音乐播放器,第三方支付等。如 果仅仅只是为了开启一个后台任务那么可以使用 startService()方法。 9.说说 Activity、Intent、Service 是什么关系 他们都是 Android 开发中使用频率最高的类。其中 Activity 和 Service 都是 Android 四大组件 之一。他俩都是 Context 类的子类 ContextWrapper 的子类,因此他俩可以算是兄弟关系吧。不过 兄弟俩各有各自的本领,Activity 负责用户界面的显示和交互,Service 负责后台任务的处理。Activity 和 Service 之间可以通过 Intent 传递数据,因此可以把 Intent 看作是通信使者。 10.请描述一下 BroadcastReceiver BroadCastReceiver 是 Android 四大组件之一,主要用于接收系统或者 app 发送的广播事件。 广播分两种:有序广播和无序广播。 内部通信实现机制:通过 Android 系统的 Binder 机制实现通信。 1. 无序广播:完全异步,逻辑上可以被任何广播接收者接收到。优点是效率较高。缺点是一个接收者不 能将处理结果传递给下一个接收者,并无法终止广播 intent 的传播。 2. 有序广播:按照被接收者的优先级顺序,在被接收者中依次传播。比如有三个广播接收者 A,B,C, 优先级是 A > B > C。那这个消息先传给 A,再传给 B,最后传给 C。每个接收者有权终止广播,比 如 B 终止广播,C 就无法接收到。此外 A 接收到广播后可以对结果对象进行操作,当广播传给 B 时, B 可以从结果对象中取得 A 存入的数据。 在通过 Context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras)时我们可以指定 resultReceiver 广播接收者,这个接收者我们 可以认为是最终接收者,通常情况下如果比他优先级更高的接收者如果没有终止广播,那么他的 onReceive 会被执行两次,第一次是正常的按照优先级顺序执行,第二次是作为最终接收者接收。 如果比他优先级高的接收者终止了广播,那么他依然能接收到广播 11.为什么要用 ContentProvider?它和 sql 的实现上有什么差别? ContentProvider 屏蔽了数据存储的细节,内部实现对用户完全透明,用户只需要关心操作数据的 uri 就可以了,ContentProvider 可以实现不同 app 之间共享。 Sql 也有增删改查的方法,但是 sql 只能查询本应用下的数据库。而 ContentProvider 还可 以去增删改查本地文件. xml 文件的读取等。 12.说说 ContentProvider、ContentResolver、ContentObserver 之间的关系 a. ContentProvider 内容提供者,用于对外提供数据 b. ContentResolver.notifyChange(uri)发出消息 c. ContentResolver 内容解析者,用于获取内容提供者提供的数据 d. ContentObserver 内容监听器,可以监听数据的改变状态 e. ContentResolver.registerContentObserver()监听消息。 View 相关 1.onInterceptTouchEvent()和onTouchEvent()的区别 onInterceptTouchEvent()用于拦截触摸事件 onTouchEvent()用于处理触摸事件 2.RemoteView在哪些功能中使用 APPwidget和Notification中 3. SurfaceView和View的区别是什么? SurfaceView中采用了双缓存技术,在单独的线程中更新界面 View在UI线程中更新界面 4.View的绘制过程 一个View要显示在界面上,需要经历一个View树的遍历过程,这个过程又可以分为三个过程,也就是自定义View中的三要素:大小,位置,画什么,即onMesure(),onLayout(),onDraw()。 1.onMesure()确定一个View的大小; 2.onLayout()确定View在父节点上的位置; 3.onDraw()绘制View 的内容; 5.如何自定义ViewGroup 1.指定的LayoutParams 2.onMeasure中计算所有childView的宽和高,然后根据childView的宽和高,计算自己的宽和高。(当然,如果不是wrap_content,直接使用父ViewGroup传入的计算值即可) 3.onLayout中对所有的childView进行布局。 6.View中onTouch,onTouchEvent,onClick的执行顺序 dispatchTouchEvent—->onTouch—->onTouchEvent—–>onClick。在所有ACTION_UP事件之后才触发onClick点击事件。 性能优化相关 1.ListView卡顿的原因与性能优化,越多越好 重用converView: 通过复用converview来减少不必要的view的创建,另外Infalte操作会把xml文件实例化成相应的View实例,属于IO操作,是耗时操作。 减少findViewById()操作: 将xml文件中的元素封装成viewholder静态类,通过converview的setTag和getTag方法将view与相应的holder对象绑定在一起,避免不必要的findviewbyid操作 避免在 getView 方法中做耗时的操作: 例如加载本地 Image 需要载入内存以及解析 Bitmap ,都是比较耗时的操作,如果用户快速滑动listview,会因为getview逻辑过于复杂耗时而造成滑动卡顿现象。用户滑动时候不要加载图片,待滑动完成再加载,可以使用这个第三方库glide Item的布局层次结构尽量简单,避免布局太深或者不必要的重绘 尽量能保证 Adapter 的 hasStableIds() 返回 true 这样在 notifyDataSetChanged() 的时候,如果item内容并没有变化,ListView 将不会重新绘制这个 View,达到优化的目的 在一些场景中,ScollView内会包含多个ListView,可以把listview的高度写死固定下来。 由于ScollView在快速滑动过程中需要大量计算每一个listview的高度,阻塞了UI线程导致卡顿现象出现,如果我们每一个item的高度都是均匀的,可以通过计算把listview的高度确定下来,避免卡顿现象出现 使用 RecycleView 代替listview: 每个item内容的变动,listview都需要去调用notifyDataSetChanged来更新全部的item,太浪费性能了。RecycleView可以实现当个item的局部刷新,并且引入了增加和删除的动态效果,在性能上和定制上都有很大的改善 ListView 中元素避免半透明: 半透明绘制需要大量乘法计算,在滑动时不停重绘会造成大量的计算,在比较差的机子上会比较卡。 在设计上能不半透明就不不半透明。实在要弄就把在滑动的时候把半透明设置成不透明,滑动完再重新设置成半透明。 尽量开启硬件加速: 硬件加速提升巨大,避免使用一些不支持的函数导致含泪关闭某个地方的硬件加速。当然这一条不只是对 ListView。 2.如何避免 OOM 问题的出现 使用更加轻量的数据结构 例如,我们可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构。通常的HashMap的实现方式更加消耗内存,因为它需要一个额外的实例对象来记录Mapping操作。另外,SparseArray更加高效,在于他们避免了对key与value的自动装箱(autoboxing),并且避免了装箱后的解箱。 避免在Android里面使用Enum Android官方培训课程提到过“Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.”,具体原理请参考《Android性能优化典范(三)》,所以请避免在Android里面使用到枚举。 减小Bitmap对象的内存占用 Bitmap是一个极容易消耗内存的大胖子,减小创建出来的Bitmap的内存占用可谓是重中之重,,通常来说有以下2个措施: ++inSampleSize++:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。 ++decode format++:解码格式,选择ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差异 Bitmap对象的复用 缩小Bitmap的同时,也需要提高BitMap对象的复用率,避免频繁创建BitMap对象,复用的方法有以下2个措施 LRUCache : “最近最少使用算法”在Android中有极其普遍的应用。ListView与GridView等显示大量图片的控件里,就是使用LRU的机制来缓存处理好的Bitmap,把近期最少使用的数据从缓存中移除,保留使用最频繁的数据, inBitMap高级特性:利用inBitmap的高级特性提高Android系统在Bitmap分配与释放执行效率。使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放Bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小 使用更小的图片 在涉及给到资源图片时,我们需要特别留意这张图片是否存在可以压缩的空间,是否可以使用更小的图片。尽量使用更小的图片不仅可以减少内存的使用,还能避免出现大量的InflationException。假设有一张很大的图片被XML文件直接引用,很有可能在初始化视图时会因为内存不足而发生InflationException,这个问题的根本原因其实是发生了OOM。 StringBuilder 在有些时候,代码中会需要使用到大量的字符串拼接的操作,这种时候有必要考虑使用StringBuilder来替代频繁的“+”。 避免在onDraw方法里面执行对象的创建 类似onDraw等频繁调用的方法,一定需要注意避免在这里做创建对象的操作,因为他会迅速增加内存的使用,而且很容易引起频繁的gc,甚至是内存抖动。 避免对象的内存泄露 3.三级缓存的原理 从缓存中加载。 从本地文件中加载(数据库,SD) 从网络加载。 a.加载 bitmap 的时候无需考虑 bitmap 加载过程中出现的 oom(内存溢出)和 android 容器快速 滑动的时候出现的图片错位等现象。(16M) b. 支持加载网络图片和本地图片。 c. 内存管理使用的 lru 算法(移除里面是有频率最少的对象),更好的管理 bitmap 的内存 Android其他 1.讲一下android中进程的优先级? 前台进程 可见进程 服务进程 后台进程 空进程 2.介绍Handle的机制 Handler通过调用sendmessage方法把消息放在消息队列MessageQueue中,Looper负责把消息从消息队列中取出来,重新再交给Handler进行处理,三者形成一个循环 通过构建一个消息队列,把所有的Message进行统一的管理,当Message不用了,并不作为垃圾回收,而是放入消息队列中,供下次handler创建消息时候使用,提高了消息对象的复用,减少系统垃圾回收的次数 每一个线程,都会单独对应的一个looper,这个looper通过ThreadLocal来创建,保证每个线程只创建一个looper,looper初始化后就会调用looper.loop创建一个MessageQueue,这个方法在UI线程初始化的时候就会完成,我们不需要手动创建 3.Dalvik虚拟机与JVM有什么区别 Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候,花费的时间更短。 Dalvik执行.dex格式的字节码,而JVM执行.class格式的字节码。 4.每个应用程序对应多少个Dalvik虚拟机 每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行 ,而所有的Android应用的线程都对应一个Linux线程 5.应用常驻后台,避免被第三方杀掉的方法 Service设置成START_STICKY kill 后会被重启(等待5秒左右),重传Intent,保持与重启前一样 通过 startForeground将进程设置为前台进程, 做前台服务,优先级和前台应用一个级别,除非在系统内存非常缺,否则此进程不会被 kill 双进程Service: 让2个进程互相保护对方,其中一个Service被清理后,另外没被清理的进程可以立即重启进程 用C编写守护进程(即子进程) : Android系统中当前进程(Process)fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活,并不受影响(Android5.0以上的版本不可行 联系厂商,加入白名单 6.根据自己的理解描述下Android数字签名。 所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序 Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证 如果要正式发布一个Android程序,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。 数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。 7.Dalvik基于JVM的改进 几个class变为一个dex,constant pool,省内存 Zygote,copy-on-write shared,省内存,省cpu,省电 基于寄存器的bytecode,省指令,省cpu,省电 Trace-based JIT,省cpu,省电,省内存 8.ARGB_8888占用内存大小 本题的答案,是4byte,即ARGB各占用8个比特来描述。 9.apk安装卸载的原理 安装过程:复制apk安装包到data/app目录下,解压并扫描安装包,把dex文件(dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。 卸载过程:删除安装过程中在上述三个目录下创建的文件及目录。 10.通过Intent传递一些二进制数据的方法有哪些? 使用Serializable接口实现序列化,这是Java常用的方法。 实现Parcelable接口,这里Android的部分类比如Bitmap类就已经实现了,同时Parcelable在Android AIDL中交换数据也很常见的。 11.横竖屏切换时Activity的生命周期 此时的生命周期跟清单文件里的配置有关系。 不设置Activity的android:configChanges时,切屏会重新调用各个生命周期默认首先销毁当前activity,然后重新加载。 设置Activity android:configChanges=”orientation|keyboardHidden|screenSize”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法 12.Serializable 和 Parcelable 的区别 在使用内存的时候,Parcelable 类比 Serializable 性能高,所以推荐使用 Parcelable 类。 1. Serializable 在序列化的时候会产生大量的临时变量,从而引起频繁的 GC。 2. Parcelable 不能使用在要将数据存储在磁盘上的情况。尽管 Serializable 效率低点,但在这 种情况下,还是建议你用 Serializable 。 13.Android 中如何捕获未捕获的异常 自 定 义 一 个 Application , 比 如 叫 MyApplication 继 承 Application 实 现 UncaughtExceptionHandler。 覆写 UncaughtExceptionHandler 的 onCreate 和 uncaughtException 方法。 14.Android 的权限规则 Android 中的 apk 必须签名 基于 UserID 的进程级别的安全机制 默认 apk 生成的数据对外是不可见的 AndroidManifest.xml 中的显式权限声明 15.多线程间通信和多进程之间通信有什么不同,分别怎么实现? 一、进程间的通信方式 1. 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的 进程间使用。进程的亲缘关系通常是指父子进程关系。 2. 有名管道 (namedpipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的 通信。 3. 信号量(semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它 常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进 程间以及同一进程内不同线程之间的同步手段。 4. 消息队列( messagequeue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符 标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。 5. 信号 (sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。 6. 共享内存(shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内 存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间 通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间 的同步和通信。 7. 套接字(socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同 及其间的进程通信。 二、线程间的通信方式 1. 锁机制:包括互斥锁、条件变量、读写锁 *互斥锁提供了以排他方式防止数据结构被并发修改的方法。 *读写锁允许多个线程同时读共享数据,而对写操作是互斥的。 *条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁 的保护下进行的。条件变量始终与互斥锁一起使用。 2. 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量 3. 信号机制(Signal):类似进程间的信号处理 线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机 制。 16.说说 LruCache 底层原理 LruCache 使用一个 LinkedHashMap 简单的实现内存的缓存,没有软引用,都是强引用。如果添 加的数据大于设置的最大值,就删除最先缓存的数据来调整内存。 maxSize 是通过构造方法初始化的值,他表示这个缓存能缓存的最大值是多少。 size 在添加和移除缓存都被更新值,他通过 safeSizeOf 这个方法更新值。safeSizeOf 默认返回 1, 但一般我们会根据 maxSize 重写这个方法,比如认为 maxSize 代表是 KB 的话,那么就以 KB 为单 位返回该项所占的内存大小。 除异常外首先会判断 size 是否超过 maxSize,如果超过了就取出最先插入的缓存,如果不为空就 删掉,并把 size 减去该项所占的大小。这个操作将一直循环下去,直到 size 比 maxSize 小或者缓存 为空。 本文转自 一点点征服 博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/7513718.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

初级Java面试

Java基本数据类型(8种) 整型:byte、short、int、long 对应字节(8 16 32 64) 浮点型:float、double 对应字节(32 64) Boolean型:boolean 对应字节(1) 字符型:char 对应字节(64) string、stringBuffer、stringBuilder string 若连接后得到的字符串在静态存储区中早已存在,那么使用“+”优于stringBuilder string能被继承吗? 不能,因为string被final修饰,string为常量,定义后不能修改 stringBuffer与stringBuilder的区别 stringBuffer(字符串常量)---线程安全 stringBuilder(字符串常量)---线程非安全 Array和ArrayList的区别 Array可以容纳基本类型和对象,而ArrayList只能容纳对象 Array是指定大小的,ArrayList是大小固定的 Array没有提供ArrayList那么多功能 适用与Array的场景 如果列表的大小已经指定,大部分情况是存储和遍历它们 对于遍历基本数据类型,尽管Collection使用自动装箱来减轻编码任务,在指定大小的基本类型的列表上工作也会变得很慢 ArrayList和LinkedList的区别:(使用迭代进行遍历) ArrayList和LinkedList均实现了List接口 ArrayList:实现了所有可选操作列表,包括null 特点: 查询快、增删慢(快:集合的特点,内存地址是连续的,只要知道一个,后面的都可以得到 慢:删除或增加后,该索引后的所有数据进行copy,所以较慢) LinkedList:链表数据结构 特点:查询慢,增删快(快:只是修改记录的前一个元素记录的内存地址发生改变 慢:挨个查询进行比较) LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储两个引用 类的实例化 类:指描述一种事物的定义,是一个抽象的概念,是一些事物具有相同的特性的集合 实例:该种事物的一个具体的个体,是具体的东西 例:”动物“是一个类,”猫“和”狗“就是实例 实例化的顺序 父类静态变量>父类静态代码块>子类静态变量>子类静态代码块>父类非静态变量(实例成员)>父类构造函数>子类非静态变量(子类实力成员变量)>子类构造函数 构造函数 是一种特殊的方法,主要用来创建对象时初始化对象,即为对象成员变量赋值 构造函数的重载 特别的类有多个构造函数,使用参数个数不同或或参数的类型进行区分 特点:函数名与类名完全相同,无返回值,无修饰符(包括void)不能被直接调用,须new Map类(key--value型) HashMap 依赖于哈希表实现,存储位置根据键的哈希码计算的 TreeMap 使用红黑树(二叉树),根据键的数据进行排序存储的(默认升序) 区别 HashMap是线程非安全的,TreeMap是线程安全的 抽象类和接口的区别 抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象 抽象类要被子类继承,接口要被类实现 接口只能做方法申明,抽象类可以做方法申明,也可以做方法实现 接口是定义的变量,只能是公共的静态的常量,抽象类中的变量是普通变量 抽象类与抽象接口中的所有方法,必须被子类(实现类)全部实现,否则子类也为抽象类,接口 抽象方法只能申明,不能实现 抽象类中可以没有抽象方法 如果一个类中有抽象方法,那么这个类只能是抽象类 抽象方法要被实现,所以不能是静态的,也不能是私有的 接口可以继承接口,并可以多继承,但类只能单继承 equals与==的区别 ==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相同 Object有哪些公用方法 方法equals测试的是两个对象是否相等 方法clone进行对象拷贝 方法getClass返回和当前对象相关的class对象 方法notify、notifall、wait都是用来对给定对象进行线程同步的 Override与Overload的含义机区别 Overload顾名思义是重新加载 它可以表现类的多重性,在函数里面可以有相同的函数名但是参数名、返回值、类型不能相同、或者说可以改变参数、类型、返回值但是函数名不变 Overrider是重写 在子类继承父类的时候子类中可以定义某方法与其父类有相同的名称和参数,当子类在调用这一个函数时自动调用子类的方法,而父类相当于被覆盖了 多态 抽象的讲:多态就是同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息即为函数调用) 实现的原理是动态绑定,程序调用的方法在运行期才动态绑定,追朔源码可以发现,jvm通过参数的自动转型来找到公用的方法 面向对象是什么 面型对象是一种思想,世间万物都可以看作是一个对象,这里是讨论面向对象编程(oop),java是一个支持并发,基于类和面向对象的计算机编程语言 面向对象软件开发的优点 代码开发模块化 代码复用性强 增强代码的可靠性和灵活性 增加代码的可读性 面向对象的四大基本特性 抽象 提取现实世界中某事物的关键特性,为该事物构建模型的过程 封装 可以使类具有独立性和隔离性,保证类的高内聚,只暴露给外部或子类必须的属性和方法 继承 对现有类的一种复用机制 多态 多态是在继承的基础上实现的,三要素(1. 继承 2. 重写 3. 父类引用指向子类对象)父类引用指向不同的子类对象时,调用相同的方法,呈现出不同的行为,就是类的多态性,多态可分为编译时、运行时抽象、封装、继承和多态是面向对象的基础 面向对象的七大设计原则 SOLID原则(单一原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则) 迪莱特原则 组合伏于继承原则(合成复用原则) 什么是值传递和引用传递 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响变量本身 引用传递是对于对象型变量而言的,传递的是该对象的一个引用,因此外部对象对引用对象所做的改变会反映到多有的对象上一般认为Java内的传递都是值传递,Java实例对象的传递是引用传递 面向对象与面向过程的区别 面向对象 把构成问题事物分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述事物在整个解决问题的步骤中的行为 面向过程 分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了面向对象是以功能划分,面向过程是以步骤划分 Java的优点 简单 只提供基本方法,减少了编程的复杂性 高效 可以用面向对象的方法描述用户的每一个动作 面向对象 平台无关性 交互式特性 面向对象的网络编程语言,支持TCP/IP协议,使得交互式更为容易 多线程机制 Java能够并行处理多项任务 动态的内存管理机制 自动垃圾回收管理机制进行内存管理 安全性 Java是解释型的(jvm) Java创建对象的几种形式 new 最常见的一种方法 调用对象的clone()方法 运用反射手段,调用Java.lang.class或者Java.lang.reflect.Constructor类的newInstance()实例方法 运用反序列化手段,调用Java.io.ObjectInputStream对象的readObject()方法 1和3都会明显的显示调用函数,2是在内存上对已有对象的影印,所以不会调用构造函数,4是从文件中还原类的对象也不会调用构造函数 是否可以从一个静态的(static)方法内部发出对非静态(non-static)方法的调用 不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,因此在调用静态方法时可能对象并没有初始化 静态变量和实例变量的区别 静态变量 被static修饰符修饰的变量,也称为类变量,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝 实例变量 必须依赖存于某一实例,需要先创建对象然后通过对象才能访问到它,静态变量可以实现让多个对象共享内存,在Java开发中,上下文类和工具中通常会有大量的静态成员 如何实现对象克隆 两种方式 实现cloneable接口并重写Object类中的clone()方法 实现Serializable接口通过对象的序列化和反序列化实现克隆,可以实现真正的clone 构造函数 构造函数用于初始化对象的状态,与方法类似,构造函数还包含在创建对象时执行的语句集合(即指令) 每次使用new关键字创建对象时,都会调用至少一个构造函数,用以将初始值分配给同一类的数据成员,(构造函数在对象或实例创建时被调用) 构造函数的编写规则 类的构造函数必须与它所在的类名具有相同的名称 Java中的构造函数不能是抽象的(abstract)、最终的(final)、静态的(static)的同步的(synchronized) 访问修饰符可以用在构造函数申明中来控制它的访问即哪个其他类可以调用构造函数 Class.forName(String className)这个方法的作用 通过类的全名获得该类的类对象 AOP、OOP、IOC、DI AOP(面向切面编程) 将通用需求功能从不相关的类中分离出来,同时能够使得很多类共享一个行为,一旦行为发生变化,不必修改很多类,只要修改行为即可 OOP(面向对象编程) 是一种计算机编程架构 IOC(控制反转) 控制指的是程序相关类之间的依赖关系,传统观念设计授内阁通常由调用者来创建被调用着的实例,在spring里,创建被调用者的工作不再由调用者来完成,而是由spring容器完成,依赖关系被反转了,成为控制反转,目的是为了获得更好的扩展性和良好的可维护性 DI(依赖注入) 创建被调用者的工作由spring容器完成,然后注入调用者,因此也称依赖注入,控制反转和依赖注入是同一个概念 Java中final关键字有哪些用法 修饰类 表示该类不能被继承 修饰方法 表示方法不能被重写 修饰变量 表示变量只能一次赋值以后值不能被修改(常量) 什么时候用assert assert(断言)常用的调试方式,保证程序最基本、关键的正确性,在软件发布后,assertion检查通常是关闭的 final,finally,finalize的区别 final 修饰符(修饰类、修饰方法、修饰变量) finally 通常放在try……catch后,只要jvm不关闭都执行,内一般写释放外部资源的代码 finalize Object中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作,这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或执行其他清理工作

优秀的个人博客,低调大师

Redis面试总结

什么是redis? Redis是一个基于内存的高性能key-value数据库。 (有空再补充,有理解错误或不足欢迎指正) Reids的特点 Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。 因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。 Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能,比方说用他的List来做FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set可以做高性能的tag系统等等。 另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一 个功能加强版的memcached来用。 Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。 Redis支持的数据类型 Redis通过Key-Value的单值不同类型来区分, 以下是支持的类型: Strings Lists Sets 求交集、并集 Sorted Set hashes 为什么redis需要把所有数据放到内存中? Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。 如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。 如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。 Redis是单进程单线程的 redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销 虚拟内存 当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大. 当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value. vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的. 可能会造成比较长时间的延迟,但是对数据完整性有很好的保证. 自己测试的时候发现用虚拟内存性能也不错。如果数据量很大,可以考虑分布式或者其他数据库 分布式 redis支持主从的模式。原则:Master会将数据同步到slave,而slave不会将数据同步到master。Slave启动时会连接master来同步数据。 这是一个典型的分布式读写分离模型。我们可以利用master来插入数据,slave提供检索服务。这样可以有效减少单个机器的并发访问数量。 读写分离模型 通过增加Slave DB的数量,读的性能可以线性增长。为了避免Master DB的单点故障,集群一般都会采用两台Master DB做双机热备,所以整个集群的读和写的可用性都非常高。 读写分离架构的缺陷在于,不管是Master还是Slave,每个节点都必须保存完整的数据,如果在数据量很大的情况下,集群的扩展能力还是受限于单个节点的存储能力,而且对于Write-intensive类型的应用,读写分离架构并不适合。 数据分片模型 为了解决读写分离模型的缺陷,可以将数据分片模型应用进来。 可以将每个节点看成都是独立的master,然后通过业务实现数据分片。 结合上面两种模型,可以将每个master设计成由一个master和多个slave组成的模型。 Redis的回收策略 volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰 volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰 volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰 allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰 allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰 no-enviction(驱逐):禁止驱逐数据 1. 使用Redis有哪些好处? 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1) 支持丰富数据类型,支持string,list,set,sorted set,hash 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除 2. redis相比memcached有哪些优势? memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型 redis的速度比memcached快很多 redis可以持久化其数据 3. redis常见性能问题和解决方案: Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内 尽量避免在压力很大的主库上增加从库 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3... 这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。 4. MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据 相关知识:redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。 redis 提供 6种数据淘汰策略,上文已经列出。 5. Memcache与Redis的区别都有哪些? 1)、存储方式 Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis有部份存在硬盘上,这样能保证数据的持久性。 2)、数据支持类型 Memcache对数据类型支持相对简单。 Redis有复杂的数据类型。 3)、使用底层模型不同 它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。 Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。 4)、value大小 redis最大可以达到1GB,而memcache只有1MB 6. Redis 常见的性能问题都有哪些?如何解决? 1).Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照。 2).Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。 Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。 3).Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。 4). Redis主从复制的性能问题,为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内 7,redis 最适合的场景 Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别。 那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢? 如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点: Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。 Redis支持数据的备份,即master-slave模式的数据备份。 Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。 (1)、会话缓存(Session Cache) 最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会这样吗? 幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。 (2)、全页缓存(FPC) 除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。 再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。 此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。 (3)、队列 Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。 如果你快速的在Google中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这里去查看。 (4),排行榜/计数器 Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像下面一样执行即可: 当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行: ZRANGE user_scores 0 10 WITHSCORES Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可以在这里看到。 (5)、发布/订阅 最后(但肯定不是最不重要的)是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!(不,这是真的,你可以去核实)。 Redis提供的所有特性中,我感觉这个是喜欢的人最少的一个,虽然它为用户提供如果此多功能。 欢迎工作一到五年的Java工程师朋友们加入Java架构开发:860113481 群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

优秀的个人博客,低调大师

java面试宝典

面向对象编程(OOP) Java是一个支持并发、基于类和面向对象的计算机编程语言。下面列出了面向对象软件开发的优点: 代码开发模块化,更易维护和修改。 代码复用。 增强代码的可靠性和灵活性。 增加代码的可理解性。 面向对象编程有很多重要的特性,比如:封装,继承,多态和抽象。下面的章节我们会逐个分析这些特性。 封装 封装给对象提供了隐藏内部特性和行为的能力。对象提供一些能被其他对象访问的方法来改变它内部的数据。在Java当中,有4种修饰符:public,private、protected和默认。每一种修饰符给其他的位于同一个包或者不同包下面对象赋予了不同的访问权限。 下面列出了使用封装的一些好处: 通过隐藏对象的属性来保护对象内部的状态。 提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展。 禁止对象之间的不良交互提高模块化。 参考这个文档获取更多关于封装的细节和示例。 多态 多态是编程语言给不同的底层数据类型做相同的接口展示的一种能力。一个多态类型上的操作可以应用到其他类型的值上面。 继承 继承给对象提供了从基类获取字段和方法的能力。继承提供了代码的重用行,也可以在不修改类的情况下给现存的类添加新特性。 抽象 抽象是把想法从具体的实例中分离出来的步骤,因此,要根据他们的功能而不是实现细节来创建类。Java支持创建只暴漏接口而不包含方法实现的抽象的类。这种抽象技术的主要目的是把类的行为和实现细节分离开。 抽象和封装的不同点 抽象和封装是互补的概念。一方面,抽象关注对象的行为。另一方面,封装关注对象行为的细节。一般是通过隐藏对象内部状态信息做到封装,因此,封装可以看成是用来提供抽象的一种策略。 常见的Java问题 什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。 JDK和JRE的区别是什么? Java运行时环境(JRE)是将要执行Java程序的Java虚拟机。它同时也包含了执行applet需要的浏览器插件。Java开发工具包(JDK)是完整的Java软件开发包,包含了JRE,编译器和其他的工具(比如:JavaDoc,Java调试器),可以让开发者开发、编译、执行Java应用程序。 ”static”关键字是什么意思?Java中是否可以覆盖(override)一个private或者是static的方法? “static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。 Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。 是否可以在static环境中访问非static变量? static变量在Java中是属于类的,它在所有的实例中的值是一样的。当类被Java虚拟机载入的时候,会对static变量进行初始化。如果你的代码尝试不用实例来访问非static的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。 Java支持的数据类型有哪些?什么是自动拆装箱? Java语言支持的8中基本数据类型是: byte short int long float double boolean char 自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。比如:把int转化成Integer,double转化成double,等等。反之就是自动拆箱。 Java中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思? Java中的方法重载发生在同一个类里面两个或者是多个方法的方法名相同但是参数不同的情况。与此相对,方法覆盖是说子类重新定义了父类的方法。方法覆盖必须有相同的方法名,参数列表和返回类型。覆盖者可能不会限制它所覆盖的方法的访问。 Java中,什么是构造函数?什么是构造函数重载?什么是复制构造函数? 当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一个默认的构造函数。 Java中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数必须有它自己唯一的参数列表。 Java不支持像C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java不会创建默认的复制构造函数。 Java支持多继承么? 不支持,Java不支持多继承。每个类都只能继承一个类,但是可以实现多个接口。 接口和抽象类的区别是什么? Java提供和支持创建抽象类和接口。它们的实现有共同点,不同点在于: 接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。 类可以实现很多个接口,但是只能继承一个抽象类 类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。 抽象类可以在不提供接口方法实现的情况下实现接口。 Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。 Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。 接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。 也可以参考JDK8中抽象类和接口的区别 什么是值传递和引用传递? 对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响源对象的值。 对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象所做的改变会反映到所有的对象上。 Java线程 进程和线程的区别是什么? 进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。 创建线程有几种不同的方式?你喜欢哪一种?为什么? 有三种方式可以用来创建线程: 继承Thread类 实现Runnable接口 应用程序可以使用Executor框架来创建线程池 实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别的对象的情况下,这需要多继承(而Java不支持多继承),只能实现接口。同时,线程池也是非常高效的,很容易实现和使用。 概括的解释下线程的几种可用状态。 线程在执行过程中,可以处于下面几种状态: 就绪(Runnable):线程准备运行,不一定立马就能开始执行。 运行中(Running):进程正在执行线程的代码。 等待中(Waiting):线程处于阻塞的状态,等待外部的处理结束。 睡眠中(Sleeping):线程被强制睡眠。 I/O阻塞(Blocked on I/O):等待I/O操作完成。 同步阻塞(Blocked on Synchronization):等待获取锁。 死亡(Dead):线程完成了执行。 同步方法和同步代码块的区别是什么? 在Java语言中,每一个对象有一把锁。线程可以使用synchronized关键字来获取对象上的锁。synchronized关键字可应用在方法级别(粗粒度锁)或者是代码块级别(细粒度锁)。 在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步? 监视器和锁在Java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。 什么是死锁(deadlock)? 两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程都陷入了无限的等待中。 如何确保N个线程可以访问N个资源同时又不导致死锁? 使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。 Java集合类 Java集合类框架的基本接口有哪些? Java集合类提供了一套设计良好的支持对一组对象进行操作的接口和类。Java集合类里面最基本的接口有: Collection:代表一组对象,每一个对象都是它的子元素。 Set:不包含重复元素的Collection。 List:有顺序的collection,并且可以包含重复元素。 Map:可以把键(key)映射到值(value)的对象,键不能重复。 为什么集合类没有实现Cloneable和Serializable接口? 集合类接口指定了一组叫做元素的对象。集合类接口的每一种具体的实现类都可以选择以它自己的方式对元素进行保存和排序。有的集合类允许重复的键,有些不允许。 什么是迭代器(Iterator)? Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的 迭代方法。迭代器可以在迭代的过程中删除底层集合的元素。 克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。 Iterator和ListIterator的区别是什么? 下面列出了他们的区别: Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。 Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。 ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。 快速失败(fail-fast)和安全失败(fail-safe)的区别是什么? Iterator的安全失败是基于对底层集合做拷贝,因此,它不受源集合上修改的影响。java.util包下面的所有的集合类都是快速失败的,而java.util.concurrent包下面的所有的类都是安全失败的。快速失败的迭代器会抛出ConcurrentModificationException异常,而安全失败的迭代器永远不会抛出这样的异常。 Java中的HashMap的工作原理是什么? Java中的HashMap是以键值对(key-value)的形式存储元素的。HashMap需要一个hash函数,它使用hashCode()和equals()方法来向集合/从集合添加和检索元素。当调用put()方法的时候,HashMap会计算key的hash值,然后把键值对存储在集合中合适的索引上。如果key已经存在了,value会被更新成新值。HashMap的一些重要的特性是它的容量(capacity),负载因子(load factor)和扩容极限(threshold resizing)。 hashCode()和equals()方法的重要性体现在什么地方? Java中的HashMap使用hashCode()和equals()方法来确定键值对的索引,当根据键获取值的时候也会用到这两个方法。如果没有正确的实现这两个方法,两个不同的键可能会有相同的hash值,因此,可能会被集合认为是相等的。而且,这两个方法也用来发现重复元素。所以这两个方法的实现对HashMap的精确性和正确性是至关重要的。 HashMap和Hashtable有什么区别? HashMap和Hashtable都实现了Map接口,因此很多特性非常相似。但是,他们有以下不同点: HashMap允许键和值是null,而Hashtable不允许键或者值是null。 Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线 程环境。 HashMap提供了可供应用迭代的键的集合,因此,HashMap是快速失败的。另一方面,Hashtable提供了对键的列举(Enumeration)。 一般认为Hashtable是一个遗留的类。 数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用Array而不是ArrayList? 下面列出了Array和ArrayList的不同点: Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。 Array大小是固定的,ArrayList的大小是动态变化的。 ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。 对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。 ArrayList和LinkedList有什么区别? ArrayList和LinkedList都实现了List接口,他们有以下的不同点: ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。 相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。 LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。 也可以参考ArrayList vs. LinkedList。 Comparable和Comparator接口是干什么的?列出它们的区别。 Java提供了只包含一个compareTo()方法的Comparable接口。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。 Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序,返回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。equals()方法需要一个对象作为参数,它用来决定输入参数是否和comparator相等。只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时候,这个方法才返回true。 什么是Java优先级队列(Priority Queue)? PriorityQueue是一个基于优先级堆的无界队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。 你了解大O符号(big-O notation)么?你能给出不同数据结构的例子么? 大O符号描述了当数据结构里面的元素增加的时候,算法的规模或者是性能在最坏的场景下有多么好。 大O符号也可用来描述其他的行为,比如:内存消耗。因为集合类实际上是数据结构,我们一般使用大O符号基于时间,内存和性能来选择最好的实现。大O符号可以对大量数据的性能给出一个很好的说明。 如何权衡是使用无序的数组还是有序的数组? 有序数组最大的好处在于查找的时间复杂度是O(log n),而无序数组是O(n)。有序数组的缺点是插入操作的时间复杂度是O(n),因为值大的元素需要往后移动来给新元素腾位置。相反,无序数组的插入时间复杂度是常量O(1)。 Java集合类框架的最佳实践有哪些? 根据应用的需要正确选择要使用的集合的类型对性能非常重要,比如:假如元素的大小是固定的,而且能事先知道,我们就应该用Array而不是ArrayList。 有些集合类允许指定初始容量。因此,如果我们能估计出存储的元素的数目,我们可以设置初始容量来避免重新计算hash值或者是扩容。 为了类型安全,可读性和健壮性的原因总是要使用泛型。同时,使用泛型还可以避免运行时的ClassCastException。 使用JDK提供的不变类(immutable class)作为Map的键可以避免为我们自己的类实现hashCode()和equals()方法。 编程的时候接口优于实现。 底层的集合实际上是空的情况下,返回长度是0的集合或者是数组,不要返回null。 Enumeration接口和Iterator接口的区别有哪些? Enumeration速度是Iterator的2倍,同时占用更少的内存。但是,Iterator远远比Enumeration安全,因为其他线程不能够修改正在被iterator遍历的集合里面的对象。同时,Iterator允许调用者删除底层集合里面的元素,这对Enumeration来说是不可能的。 HashSet和TreeSet有什么区别? HashSet是由一个hash表来实现的,因此,它的元素是无序的。add(),remove(),contains()方法的时间复杂度是O(1)。 另一方面,TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),remove(),contains()方法的时间复杂度是O(logn)。 垃圾收集器(Garbage Collectors) Java中垃圾回收有什么目的?什么时候进行垃圾回收? 垃圾回收的目的是识别并且丢弃应用不再使用的对象来释放和重用资源。 System.gc()和Runtime.gc()会做什么事情? 这两个方法用来提示JVM要进行垃圾回收。但是,立即开始还是延迟进行垃圾回收是取决于JVM的。 finalize()方法什么时候被调用?析构函数(finalization)的目的是什么? 在释放对象占用的内存之前,垃圾收集器会调用对象的finalize()方法。一般建议在该方法中释放对象持有的资源。 如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存? 不会,在下一个垃圾回收周期中,这个对象将是可被回收的。 Java堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)? JVM的堆是运行时数据区,所有类的实例和数组都是在堆上分配内存。它在JVM启动的时候被创建。对象所占的堆内存是由自动内存管理系统也就是垃圾收集器回收。 堆内存是由存活和死亡的对象组成的。存活的对象是应用可以访问的,不会被垃圾回收。死亡的对象是应用不可访问尚且还没有被垃圾收集器回收掉的对象。一直到垃圾收集器把这些对象回收掉之前,他们会一直占据堆内存空间。 串行(serial)收集器和吞吐量(throughput)收集器的区别是什么? 吞吐量收集器使用并行版本的新生代垃圾收集器,它用于中等规模和大规模数据的应用程序。而串行收集器对大多数的小应用(在现代处理器上需要大概100M左右的内存)就足够了。 在Java中,对象什么时候可以被垃圾回收? 当对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收了。 JVM的永久代中会发生垃圾回收么? 垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免Full GC是非常重要的原因。请参考下Java8:从永久代到元数据区

优秀的个人博客,低调大师

面试

1.事务的特性 原子性 事务中的全部操作在数据库中是不分隔的,要么全部完成,要么均不执行 隔离型 事务的执行不受其他事务的干扰,事务 执行的中间结果对其他事务必须是透明的。 持久性 对于任意已提交事务,系统必须保证该 事务对数据库的改变不被丢失,即使数据库出现故障 一致性 几个并行执行的事务,其执行结果必 须与按某一顺序串行执行的结果相一致。 2.redis 和mysql的区别 redis是内存数据库,数据保存在内存中,速度快 mysql是关系型数据库,持久化存储,存放在磁盘里面,功能强大,检索的话,会涉及到一定的IO 3.Django 重定向 使用HttpResponseRedirect redirect 和 reverse 状态码:302,301 说一下Django,MIDDLEWARES 中间件的作用? 答:中间件是介于request 与 response 处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django 5.简述uwsgi与Nginx配置 a)nginx 具备优秀的静态内容处理能力, , 然后将动态内容转发给 uWSGI 服务器, , 这样可以达到很好的客户端响应 6.迭代器和生成器区别? 答::迭代器是一个更抽象的概念,有任何对如果它类有next 方法和iter方法返回自己本身 对于 strings、 、list、 、dict、 、tuple用 等这类容器对象,使用for台 循环遍历是很方便的。在后台for语句用对容器象调用 iter()函数,iter()是 是python的内置函数 。iter()会返回一个定义next()方法的迭代器对象,它在 容器 中逐个访问容器内元素,next()也是python的内置函数。在没有后续元素时next()会抛出一个StopIter 异常 ((2 2( )生成器( Generator)是创建迭代器的简单而强大工具 。 用它们写起来就像是正规的函数,只在需要返回据时候使用d yield 语 次句。每次next()被调用,生成器会返回它脱离的位置 , 记忆语句最 后一次执行和所有数据。 事区别:生成器能做到迭代的所有事, ,而且因为自动创建了 __iter__()和 和 next()法 方法, ,洁 生成器显得特别简洁, ,而且生成器也是 的高效的表,使用生成器表省达式取代列解析可以同时节省内存。除了 创建和保程序状态的自动方法, ,时 当发生器终结时, ,还会自动抛出 n StopIteration 异常。 本文转自 xxl714 51CTO博客,原文链接:http://blog.51cto.com/dreamgirl1314/1980472,如需转载请自行联系原作者

优秀的个人博客,低调大师

IOS面试宝典

Object-C有多继承吗?没有的话用什么代替? cocoa 中所有的类都是NSObject 的子类,多继承在这里是用protocol 委托代理来实现的 你不用去考虑繁琐的多继承 ,虚基类的概念.ood的多态特性 在 obj-c 中通过委托来实现. Object-C有私有方法吗?私有变量呢? objective-c– 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法 @interface Controller : NSObject { NSString *something; } + (void)thisIsAStaticMethod; – (void)thisIsAnInstanceMethod; @end @interface Controller (private) - (void)thisIsAPrivateMethod; @end @private可以用来修饰私有变量 在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的 关键字const什么含义 const意味着”只读”,下面的声明都是什么意思? const int a; int const a; const int *a; int * const a; int const * a const; 前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。 结论: 本文转自蓬莱仙羽51CTO博客,原文链接:http://blog.51cto.com/dingxiaowei/1366597,如需转载请自行联系原作者

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册