1、牛客刷题●RabbitMQ有以下几种工作模式 : work模式:一个生产者,多个消费者,每个消费者获取到的消息唯一。 订阅模式:一个生产者发送的消息会被多个消费者获取。 路由模式:发送消息到交换机并且要指定路由key ,消费者指定路由key将队列绑定到交换机 topic模式:将路由键和某模式进行匹配,此时队列需要绑定在一个模式上 String,Stringbuffer,StringBuilder的区别 String:
StringBuffer:
StringBuilder:
String s 与new String的区别
String str ="whx" 先在常量池中查找有没有"whx" 这个对象,如果有,就让str指向那个"whx".如果没有,在常量池中新建一个“whx”对象,并让str指向在常量池中新建的对象"whx"。 String newStr =new String ("whx"); 是在堆中建立的对象"whx" ,在栈中创建堆中"whx" 对象的内存地址。 反射的原理,反射创建类实例的三种方式是什么 Java反射机制: Java 的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法; 并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制 获取 Class 类对象三种方式:
JDK动态代理与cglib实现的区别
谈谈序列化与反序列化
分布式结构,怎么保证数据一致性
2、数据库相关MySQL●SQL注入 ●寻找到SQL注入的位置 ● 请你说明一下 left join 和 right join 的区别? left join(左联接) :返回包括左表中的所有记录和右表中联结字段相等的记录 ●事务是什么 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。 ● 数据库ACID的特性。 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 一致性指事务前后数据的完整性必须保持一致。 隔离性指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离。 持久性是指一个事务一旦提交,它对数据库中数据的改变就是永久性的,即便数据库发生故障也不应该对其有任何影响。 ● 请你介绍一下,数据库的三个范式? 第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。 第二范式(2NF):首先满足 1NF,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。 第三范式(3NF):首先是满足2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况 ● 请你介绍一下数据库的隔离级别
未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据。 已提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)。 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读。 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。 数据库的脏读、幻读、不可重复读 1.脏读: 指一个事务A正在访问数据,并且对该数据进行了修改,但是这种修改还没有提交到数据库中(也可能因为某些原因Rollback了)。这时候另外一个事务B也访问这个数据,然后使用了这个被A修改的数据,那么这个数据就是脏的,并不是数据库中真实的数据。这就被称作脏读。(事务A读到了事务B未提交的数据) 解决办法:把数据库事务隔离级别调整到READ_COMMITTED 即让用户在更新时锁定数据库,阻止其他用户读取,直到更新全部完成才让你读取。 2.幻读: 指一个事务A对一个表中的数据进行了修改,而且该修改涉及到表中所有的数据行;同时另一个事务B也在修改表中的数据,该修改是向表中插入一行新数据。那么经过这一番操作之后,操作事务A的用户就会发现表中还有没修改的数据行,就像发生了幻觉一样。这就被称作幻读。(事务A修改数据,事务B插入数据,A发现表中还没有修改的数据行) 解决办法:把数据库事务隔离级别调整到SERIALIZABLE_READ 3.不可重复读: 指在一个事务A内,多次读同一个数据,但是事务A没有结束时,另外一个事务B也访问该同一数据。那么在事务A的两次读数据之间,由于事务B的修改导致事务A两次读到的数据可能是不一样的。这就发生了在一个事务内两次读到的数据不一样,这就被称作不可重复读。(事务A多次读数据,事务B访问数据,A读到了B修改的数据,导致两次读到的数据不一样) 解决办法:把数据库事务隔离级别调整到REPEATABLE_READ 级别高低:脏读 < 不可重复读 < 幻读 所以设置了最高级别的SERIALIZABLE_READ就不需要设置其他的了,即解决了幻读问题那么脏度和不可重复读自然就都解决了。 ● 请你简单介绍一下,数据库水平切分与垂直切分 垂直拆分就是要把表按模块划分到不同数据库表中,单表大数据量依然存在性能瓶颈 水平切分就是要把一个表按照某种规则把数据划分到不同表或数据库里。 通俗理解:水平拆分行,行数据拆分到不同表中, 垂直拆分列,表数据拆分到不同表中。 ● 请你讲讲 Statement 和 Prepared Statement 的区别?哪个性能更好? 与Statement相比,①PreparedStatement接口代表预编译的语句,它主要的优势在于可以减少SQL的编译错误并增加SQL的安全性(减少SQL注射攻击的可能性);②PreparedStatement中的SQL语句是可以带参数的,避免了用字符串连接拼接SQL语句的麻烦和不安全;③当批量处理SQL或频繁执行相同的查询时,PreparedStatement有明显的性能上的优势,由于数据库可以将编译优化后的SQL语句缓存起来,下次执行相同结构的语句时就会很快 mysql数据库的索引类型 1、普通索引当一张表,把某个列设为主键的时候,则该列就是主键索引 2、唯一索引索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。 3、主键索引是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。 4、组合索引指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合。 5、全文索引主要用来查找文本中的关键字,而不是直接与索引中的值相比较。 InnoDB索引实现(聚集)
InnoDB主键索引查找流程:通过.ibd文件找到对应的索引,索引的value即为那行对应的完整数据 聚集索引和非聚集索引的区别? 聚集索引:表中那行数据的索引和数据都合并在一起了。 非聚集索引:表中那行数据的索引和数据是分开存储的。 一个 SQL 执行的很慢,我们要分两种情况讨论: 1、偶尔很慢,则有如下原因 (1)、数据库在刷新脏页,例如 redo log 写满了需要同步到磁盘。 (2)、执行的时候,遇到锁,如表锁、行锁。 2、这条 SQL 语句一直执行的很慢,则有如下原因。 (1)、没有用上索引:例如该字段没有索引;由于对字段进行运算、函数操作导致无法用索引。 (2)、数据库选错了索引。 Redisredis常见的数据结构以及应用场景: String:key -value缓存应用,最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。 Hash:field-value映射表,存储用户信息和商品信息 List:list分页查询 Set:实现差,并,交集操作,比如共同喜好等 Sorted set:用户列表,礼物排行榜,弹幕消息 缓存雪崩: 缓存同一时间大面积失效,所有请求都落到数据库造成短时间内承受大量请求而崩掉 如何解决缓存雪崩?在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。 对于“Redis挂掉了,请求全部走数据库”这种情况,我们可以有以下的思路: 事发前:实现Redis的高可用(主从架构+Sentinel 或者Redis Cluster),尽量避免Redis挂掉这种情况发生。 事发中:设置本地缓存(ehcache)+限流(hystrix),尽量避免我们的数据库***掉(起码能保证我们的服务还是能正常工作的) 事发后:redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。 缓存穿透: 恶意请求缓存中不存在的数据,所有求情都落到数据库造成短时间内承受大量请求而崩掉 如何解决缓存穿透? (一)利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试 (二)采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。 (三)提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。 Redis和数据库双写一致性? 首先,采取正确更新策略,先更新数据库,再删缓存。其次,因为可能存在删除缓存失败的问题,提供一个补偿措施即可,例如利用消息队列。 采用延时双删策略 (1)先淘汰缓存 Redis的内存淘汰机制:Redis提供了8种内存淘汰策略
如何解决 Redis 的并发竞争 Key 问题 基于zookeeper临时有序节点可以实现的分布式锁。大致思想为:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。 redis 持久化机制(怎么保证 redis 挂掉之后再重启数据可以进行恢复) 1、快照(snapshotting)持久化(RDB) Redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis主从结构,主要用来提高Redis性能),还可以将快照留在原地以便重启服务器的时候使用。快照持久化是Redis默认采用的持久化方式,在redis.conf配置文件中默认有此下配置 与快照持久化相比,AOF持久化 的实时性更好,因此已成为主流的持久化方案。默认情况下Redis没有开启AOF方式的持久化,可以通过appendonly参数开启.Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 ● 请问,为什么 redis 读写速率快、性能好? Redis是纯内存数据库,相对于读写磁盘,读写内存的速度就不是几倍几十倍了,一般hash查找可以达到每秒百万次的数量级。 多路复用IO,“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗)。可以直接理解为:单线程的原子操作,避免上下文切换的时间和性能消耗;加上对内存中数据的处理速度,很自然的提高redis的吞吐量。 3、SSM1、spring● 请问什么是IoC和DI?并且简要说明一下DI是如何实现的? IoC叫控制反转,DI叫依赖注入。控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。"控制反转"就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。依赖注入的基本原则是应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。DI是对IoC更准确的描述,即组件之间的依赖关系由容器在运行期决定,即由容器动态的将某种依赖关系注入到组件之中。 依赖注入是从应用程序的角度在描述:应用程序依赖容器创建并注入它所需要的外部资源; 控制反转是从容器的角度在描述:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。 ● 请说明一下springIOC原理是什么?如果你要实现IOC需要怎么做?请简单描述一下实现步骤? ①IoC这是spring的核心,由spring来负责控制对象的生命周期和对象间的关系。 IoC的一个在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI来实现的。比如对象A需要操作数据库,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像***一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。 ②实现IOC的步骤 定义用来描述bean的配置的Java类、解析bean的配置、遍历存放HashMap对象 ● 请谈一谈Spring中自动装配的方式有哪些?
bean的生命周期 ● 请简要说明一下IOC和AOP是什么? 控制反转(IoC)与依赖注入(DI)是同一个概念,引入IOC的目的:(1)脱开、降低类之间的耦合;(2)倡导面向接口编程、实施依赖倒换原则; (3)提高系统可插入、可测试、可修改等特性。 具体做法:(1)将bean之间的依赖关系尽可能地抓换为关联关系; (2)将对具体类的关联尽可能地转换为对Java interface的关联,而不是与具体的服务对象相关联; (3)Bean实例具体关联相关Java interface的哪个实现类的实例,在配置信息的元数据中描述; (4)由IoC组件(或称容器)根据配置信息,实例化具体bean类、将bean之间的依赖关系注入进来。 AOP,即面向切面编程,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",所谓"切面"是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。 使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开。 ● 请问Spring支持的事务管理类型有哪些?以及你在项目中会使用哪种方式? Spring支持编程式事务管理和声明式事务管理。许多Spring框架的用户选择声明式事务管理,因为这种方式和应用程序的关联较少,因此更加符合轻量级容器的概念。声明式事务管理要优于编程式事务管理,尽管在灵活性方面它弱于编程式事务管理,因为编程式事务允许你通过代码控制业务。 ● 你如何理解AOP中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念? a. 连接点(Joinpoint):程序执行的某个特定位置(如:某个方法调用前、调用后,方法抛出异常后)。一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就是连接点。 d. 引介(Introduction):引介是一种特殊的增强,它为类添加一些属性和方法。 ● 请问AOP的原理是什么? AOP指面向切面编程,用于处理系统中分布于各个模块的横切关注点,比如事务管理、日志、缓存等等。AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表。通常使用AspectJ的编译时增强实现AOP,AspectJ是静态代理的增强,所谓的静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强。 Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。 JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。核心是InvocationHandler接口和Proxy类。如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。 CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类 ● 请问aop的应用场景有哪些? Authentication 权限 ,Caching 缓存 ,Context passing 内容传递 ,Error handling 错误处理 ,Lazy loading 懒加载 ,Debugging 调试 ,logging, tracing, profiling and monitoring 记录跟踪 优化 校准,Performance optimization 性能优化 ,Persistence 持久化 ,Resource pooling 资源池 ,Synchronization 同步,Transactions 事务。 ● Spring框架为企业级开发带来的好处有哪些?
Aop实现的几种方式: 第一种:静态织入,即在编译时,就将各种涉及AOP拦截的代码注入到符合一定规则的类中,编译后的代码与我们直接在RealA调用属性或方法前后增加代码是相同的,只是这个工作交由编译器来完成。 第二种:EMIT反射,即:通过Emit反射动态生成代理类 第三种:普通反射+利用Remoting的远程访问对象时的直实代理类来实现 Spring如何选择用JDK还是CGLiB?
● 请问持久层设计要考虑的问题有哪些?请谈一下你用过的持久层框架都有哪些? 所谓"持久"就是将内存中的数据保存到关系型数据库、文件系统、消息队列等提供持久化支持的设备中。持久层就是系统中专注于实现数据持久化的相对独立的层面。 持久层设计的目标包括:
● 请阐述一下实体对象的三种状态是什么?以及对应的转换关系是什么? Hibernate文档中为Hibernate对象定义了四种状态,分别是:瞬时态(new, or transient)、持久态(managed, or persistent)、游状态(detached)和移除态 瞬时态:当new一个实体对象后,这个对象处于瞬时态,即这个对象只是一个保存临时数据的内存区域,如果没有变量引用这个对象,则会被JVM的垃圾回收机制回收。这个对象所保存的数据与数据库没有任何关系,除非通过Session的save()、saveOrUpdate()、persist()、merge()方法把瞬时态对象与数据库关联,并把数据插入或者更新到数据库,这个对象才转换为持久态对象。 ● 请说明一下锁机制的作用是什么?并且简述一下Hibernate的悲观锁和乐观锁机制是什么? 有些业务逻辑在执行过程中要求对数据进行排他性的访问,于是需要通过一些机制保证在此过程中数据被锁住不会被外界修改,这就是所谓的锁机制。 依赖注入的注入方式: 1、使用构造函数提供2、使用set方法提供3、使用注解提供 创建bean的方式: 1、使用默认构造函数2、使用普通工厂中的方法创建对象3、使用工厂中的静态方法创建对象 Aspectj对AOP的实现: 1)注册bean 2)配置aop 3)定义切入点 4)定义切面(哪种通知) Spring如何解决循环依赖 spring中循环依赖有三种情况: 1、构造器注入形成的循环依赖。也就是beanB需要在beanA的构造函数中完成初始化,beanA也需要在beanB的构造函数中完成舒适化,这种情况的结果就是两个bean都不能完成初始化,循环依赖难以解决。 2、setter注入构成的循环依赖。beanA需要在beanB的setter方法中完成初始化,beanB也需要在beanA的setter方法中完成初始化,spring设计的机制主要就是解决这种循环依赖 3、prototype作用域bean的循环依赖。这种循环依赖同样无法解决,因为spring不会缓存‘prototype’作用域的bean,而spring中循环依赖的解决正是通过缓存来实现的。 spring只能解决setter注入构成的依赖,第二种情况中循环依赖的解决方案: 步骤一:beanA进行初始化,并且将自己进行初始化的状态记录下来,并提前向外暴露一个单例工程方法,从而使其他bean能引用到该bean 步骤二:beanA中有beanB的依赖,于是开始初始化beanB。 步骤三:初始化beanB的过程中又发现beanB依赖了beanA,于是又进行beanA的初始化,这时发现beanA已经在进行初始化了,程序发现了存在的循环依赖,然后通过步骤一中暴露的单例工程方法拿到beanA的引用(注意,此时的beanA只是完成了构造函数的注入但为完成其他步骤),从而beanB拿到beanA的引用,完成注入,完成了初始化,如此beanB的引用也就可以被beanA拿到,从而beanA也就完成了初始化。 Spring的加载过程 初始化环境—>加载配置文件—>实例化Bean—>调用Bean显示信息 2、springmvc1.SpringMVC的流程 (1)用户发送请求至前端控制器DispatcherServlet 2.SpringMVC的主要组件? (1)前端控制器DispatcherServlet(不需要程序员开发):接收请求、响应结果,相当于转发器,有 3.SpringMVC和Struts2的区别? (1)SpringMVC的入口是一个servlet即前端控制器,而Struts2入口是一个filter过滤器 4.SpringMVC怎么样设定重定向和转发的? (1)转发:在返回值前面加forward,如forward:user.do?name=method4 5.SpringMVC怎么和ajax相互调用 通过jackson框架就可以把java里面的对象直接转化为js可以识别的json对象,具体步骤如下: (1)加入jackson.jar (2)在配置文件中配置json的映射 6.如何解决post请求中乱码问题,get的又如何处理? (1)解决post请求乱码问题 7.SpringMVC的控制器是不是单例模式,如果是,有什么问题,怎么解决? 单例模式:单例模式类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。 主要解决:一个全局使用的类频繁地创建与销毁。 何时使用:当您想控制实例数目,节省系统资源的时候。 如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。 工厂模式 工厂模式提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。 意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。 主要解决:主要解决接口选择的问题。 何时使用:我们明确地计划不同条件下创建不同实例时。 如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。 是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能,解决方案是在控制 8.SpringMVC常用的注解有哪些? @RequestMapping:用于处理请求url映射的注解,可用于类或方法上。用于类上,则表示类中的所有 9.如果在拦截请求中,我想拦截get方式提交的方法,怎么配置? 可以在@RequestMapping注解里面加上method=RequestMethod.GET 10.如果想在拦截的方法里面得到从前台传入的参数,怎么得到? 直接在形参里面声明这个参数就可以,但必须名字和传过来的参数一样。 11.SpringMVC中函数的返回值是什么? 返回值可以有多种类型,有String,void,和ModelAndView。 12.SpringMVC用什么对象从后台向前台传递数据? 通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前台就可以通过el表达式 13.注解原理 注解本质上是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。我们 3、mybatis一、什么是Mybatis?
二、Mybatis的优点 1.基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML 三、Mybatis框架的缺点: 1.SQL语句的编写工作量较大,尤其当字段多、关联表多时,编写SQL语句的功底有一定要求。 四、Mybatis与Hibernate有哪些不同? 四、#{}和${}的区别是什么? {}是预编译处理,${}是字符串替换 Mybatis在处理#{}时会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值。 五、当实体类中的属性名和表中的字段名不一样,怎么办? 1.定义字段名的别名,让字段名的别名和实体类的属性名一致。 六、模糊查询like语句该怎么写? 1.在Java代码中添加sql通配符。 七、通常一个XML映射文件,都会写一个Dao接口与之对应,请问这个Dao接口 的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗? 八、Mybatis的XML映射文件中,不同的XML映射文件,id是否可以重复? 不同的XML映射文件,如果配置了namespace,那么id可以重复,如果没有配置namespace,那么id 九、为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里? Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对 十、MyBatis实现一对一有几种方式?具体怎么操作的? 有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次,通过resultMap里面配置 十二、使用MyBatis的mapper接口调用时有哪些要求? 1.Mapper接口方法名和mapper.xml中定义的每个sql的id相同。 十三、mybatis的延迟加载 延迟加载:在真正使用数据时才发起查询,不用的时候不查询,按需加载 立即加载:不管用不用,只要一调用方法,马上发起查询 十四、Mybatis的一级缓存和二级缓存? 1)一级缓存 Mybatis的一级缓存是指SQLSession,一级缓存的作用域是SQlSession, Mybits默认开启一级缓存。 在同一个SqlSession中,执行相同的SQL查询时;第一次会去查询数据库,并写在缓存中,第二次会直接从缓存中取。 当执行SQL时候两次查询中间发生了增删改的操作,则SQLSession的缓存会被清空。 每次查询会先去缓存中找,如果找不到,再去数据库查询,然后把结果写到缓存中。 Mybatis的内部缓存使用一个HashMap,key为hashcode+statementId+sql语句。Value为查询出来的结果集映射成的java对象。 SqlSession执行insert、update、delete等操作commit后会清空该SQLSession缓存。 2)二级缓存是mapper级别的,Mybatis默认是没有开启二级缓存的。 第一次调用mapper下的SQL去查询用户的信息,查询到的信息会存放代该mapper对应的二级缓存区域。 第二次调用namespace下的mapper映射文件中,相同的sql去查询用户信息,会去对应的二级缓存内取结果。 如果调用相同namespace下的mapepr映射文件中增删改sql,并执行了commit操作 一级缓存:也称为本地缓存,用于保存用户在一次会话过程中查询的结果,用户一次会话中只能使用一个sqlSession,一级缓存是自动开启的,不允许关闭。 二级缓存:也称为全局缓存,是mapper级别的缓存,是针对一个表的查结果的存储,可以共享给所有针对这张表的查询的用户。也就是说对于mapper级别的缓存不同的sqlsession是可以共享的。 JDBC编程有哪些不足之处,Mybatis是如何解决这些问题的? 1) 数据库连接的创建、释放频繁造成系统资源浪费从而影响了性能,如果使用数据库连接池就可以解决这个问题。当然JDBC同样能够使用数据源。 2) SQL语句在写代码中不容易维护,事件需求中SQL变化的可能性很大,SQL变动需要改变JAVA代码。解决:将SQL语句配置在mapper.xml文件中与java代码分离。 3) 向SQL语句传递参数麻烦,因为SQL语句的where条件不一定,可能多,也可能少,占位符需要和参数一一对应。解决:Mybatis自动将java对象映射到sql语句。 4) 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。解决:Mbatis自动将SQL执行结果映射到java对象。 Mybatis编程步骤 ? Step1:创建SQLSessionFactory Step2:通过SQLSessionFactory创建SQLSession Step3:通过SQLSession执行数据库操作 Step4:调用session.commit()提交事物 Step5:调用session.close()关闭会话 MyBatis与hibernate有哪些不同 ? 1)Mybatis MyBatis 是支持定制化 SQL、存储过程以及高级映射的一种持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。Mybatis它不完全是一个ORM(对象关系映射)框架;它需要程序员自己编写部分SQL语句。 mybatis可以通过xml或者注解的方式灵活的配置要运行的SQL语句,并将java对象和SQL语句映射生成最终的执行的SQL,最后将SQL执行的结果在映射生成java对象。 Mybatis程序员可以直接的编写原生态的SQL语句,可以控制SQL执行性能,灵活度高,适合软件需求变换频繁的企业。 缺点:Mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套SQL映射文件,工作量大。 2) Hibernate Hibernate是支持定制化 SQL、存储过程以及高级映射的一种持久层框架。 Hibernate对象-关系映射能力强,数据库的无关性好,Hirberate可以自动生成SQL语句,对于关系模型要求高的软件,如果用HIrbernate开发可以节省很多时间。 SQLMapConfig.xml中配置有哪些内容?
Mybatis动态SQL? 传统的JDBC的方法,在组合SQL语句的时候需要去拼接,稍微不注意就会少少了一个空格,标点符号,都会导致系统错误。Mybatis的动态SQL就是为了解决这种问题而产生的;Mybatis的动态SQL语句值基于OGNL表达式的,方便在SQL语句中实现某些逻辑;可以使用标签组合成灵活的sql语句,提供开发的效率。 ORM: 对象关系映射(Object Relational Mapping,简称ORM),提供了概念性的、易于理解的模型化数据的方法,目的是想像操作对象一样操作数据库.因为数据库不是面向对象的,所以需要编程进行映射. Mabatis三剑客分别是:mybatis-generator、mybatis-plugin、mybatis-pagehelper 4、配置文件总结 web.xml** 在使用springmvc框架的时候,在处理json的时候需要用到spring框架特有的注解@ResponseBody或 4、spring cloud SpringCloud将现在非常流行的一些技术整合到一起,实现了诸如:配置管理,服务发现,智能路由,负载均衡,熔断器,控制总线,集群状态等等功能。 1、组件1、Eureka:注册中心Eureka就好比是滴滴,负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。 同时,服务提供方与Eureka之间通过
Eureka架构中的三个核心角色:
2、Zuul:服务网关 服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了 不管是来自于客户端(PC或移动端)的请求,还是服务内部调用。一切对服务的请求都会经过Zuul这个网关,然后再由网关来实现 鉴权、动态路由等等操作。Zuul就是我们服务的统一入口。 Zuul中默认就已经集成了Ribbon负载均衡和Hystix熔断机制。但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了 3、Ribbon:负载均衡负载均衡是我们处理高并发、缓解网络压力和进行服务器扩容的重要手段之一。但是,一般情况下我们 4、Feign:服务调用Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用再自己拼接url,拼接参数等等操作,一切都交给Feign去做。 Feign中本身已经集成了Ribbon依赖和自动配置、Feign默认也有对Hystix的集成、Spring Cloud Feign 支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。 5、Hystix:熔断器雪崩效应: Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。当有服务出现异常时,直接进行失败回滚,服务降级处理: 当服务繁忙时,如果服务出现异常,不是粗暴的直接报错,而是返回一个友好的提示,虽然拒绝了用户的访问,但是会返回一个结果。 这就好比去买鱼,平常超市买鱼会额外赠送杀鱼的服务。等到逢年过节,超时繁忙时,可能就不提供杀鱼服务了,这就是服务的降级。 系统特别繁忙时,一些次要服务暂时中断,优先保证主要服务的畅通,一切资源优先让给主要服务来使用,在双十一、618时,京东天猫都会采用这样的策略。 使用步骤:导入依赖--->Feign的客户端--->开启feign的功能--->启动测试 2、FastDFS3、单点登录单点登录又叫做sso,是在互相信任的多个系统中,只需要输入一次用户名密码,就可以直接登录其它 认证:判断用户名和密码是否正确 4、什么是集群?集群就是多台机器,是一种线上的部署方案,很多机器加起来,性能就比一台机器强,一般用这种部署 5、什么是docker?docker是一种容器化技术,也可以说是一种虚拟化技术。通俗的理解就是一个高性能,Linux服务器上 spring cloud和rpc框架的区别 对比: 5、spring boot一、热部署 热部署是指当我们修改代码后,服务能自动加载新修改的内容,这样大大提高了 我们开发的效率,否则 二、使用lombok 在之前编写的代码中,我们写了很多bean,这里面加了很多set、get方法,这些方法冗余,但却也不可 三、什么是SpringBoot? SpringBoot是Spring开源组织下的子项目,是Spring组件一站式解决方案,主要是简化了使用Spring的 四、SpringBoot有哪些有哪些优点? 1.减少开发,测试时间和努力 五、SpringBoot的核心配置文件有哪几个?它们的区别是什么? SpringBoot的核心配置文件是application和bootstrap配置文件 六、SpringBoot的配置文件有哪几种格式?它们有什么区别? .properties和.yml,它们的区别主要是书写格式不同。 七、Spring Boot的核心注解是哪个?它主要由哪几个注解组成的? @SpringBootApplication是SpringBoot的核心注解,主要组合包含了以下3个注解: 八、开启Spring Boot特性有哪几种方式? 1.继承spring-boot-start-parent项目 九、Spring Boot需要独立的容器运行吗? 可以不需要,内置了Tomcat/Jetty等容器。 十、运行SpringBoot有哪几种方式? 1、打包用命令或者放到容器中运行。 十一、SpringBoot自动配置原理是什么? 注解@EnableAutoConfiguration,@Configuration,@ConditionalOnClass就是自动配置的核心,首先 十二、SpringBoot实现分页和排序? 使用Spring Data-JPA可以实现将可分页的org.springframework.data.domain.Pageable传递给存储库 十三、如何实现Spring Boot应用程序的安全性? 使用spring-boot-starter-security依赖项,并且必须添加安全配置。 十四、如何集成Spring Boot和ActiveMQ? 使用spring-boot-start-activemq依赖关系。它只需要很少的配置,并且不需要样板代码。 十五、SpringBoot中的监视器是什么? Spring boot actuator是spring启动框架中的重要功能之一。spring boot监视器可帮助您访问生产环境 十六、什么是Swagger?你用Spring Boot实现了它吗? Swagger是用于生成Restful Web服务的可视化表示的工具,规范和完整框架实现。它使文档能够以与 十七、如何使用Spring Boot实现异常处理? Spring提供了一种使用ControllerAdvice处理异常的非常有用的方法。我们通过实现一个 十八、RequestMapping和GetMapping的不同之处在哪里? RequestMapping具有类属性的,可以进行GET\POST\PUT或者其它的注释中具有的请求方法 十九、Spring Boot可以兼容老Spring项目吗?如何做? 可以兼容,使用@ImportResource注解导入老Spring项目配置文件。 二十、包含Spring boot应用有哪些方法? 在生产中使用Https使用Snyk检查你的依赖关系 1.关于缓存 6、计算机网络计算机网络七层模型 TCP/IP四层模型 1.Http和Https的区别 2.对称加密与非对称加密 3.三次握手和四次挥手 tcp的几个状态:
(1)三次握手(我要和你建立连接,你真的要和我建立连接么,我真的要和你建立连接,成功): (2)四次挥手(我要和你断开连接;好的,断吧。我也要和你断开连接;好的,断吧) 4.域名系统(服务)协议(DNS)是一种分布式网络目录服务,主要用于域名与 IP 地址的相互转换,以及控制因特网的电子邮件的发送。 5.子网掩码:是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码,子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分 6.网关:网关又称网间连接器、协议转换器。网关在网络层以上实现网络互连,是复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换重任的计算机系统或设备。 7、TCP与UDP区别总结: 1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接 2、TCP提供可靠的服务。通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付 3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。 4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信 5、TCP对系统资源要求较多,UDP对系统资源要求较少。 7、Java基础● int和Integer有什么区别? 为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。 Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int是java的原始数据类型,Integer是java为int提供的封装类。 请你谈谈大O符号(big-O notation)并给出不同数据结构的例子 大O符号描述了当数据结构里面的元素增加的时候,算法的规模或者是性能在最坏的场景下有多么好。 ● 请你解释什么是值传递和引用传递? 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量. 请你说说Lamda表达式的优缺点。 优点:1. 简洁。2. 非常容易并行计算。3. 可能代表未来的编程趋势。 缺点:1. 若不用并行计算,很多时候计算速度没有比传统的 for 循环快。(并行计算有时需要预热才显示出效率优势)2. 不容易调试。3. 若其他程序员没有学过 lambda 表达式,代码不容易让其他语言的程序员看懂。 ● 你知道java8的新特性吗,请简单介绍一下 Lambda 表达式 − Lambda允许把函数作为一个方法的参数 方法引用− 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。 默认方法− 默认方法就是一个在接口里面有了一个实现的方法。 新工具− 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。 ==与equlas有什么区别? ==
equals
final关键字 当用final修饰一个类时,表明这个类不能被继承。“使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。 ● 接口和抽象类的区别是什么? Java提供和支持创建抽象类和接口。它们的实现有共同点,不同点在于: ● 请你说说Iterator和ListIterator的区别? ● 请问什么是java序列化?以及如何实现java序列化? 序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。 java内存模型(Java Memory Model)是java虚拟机规范定义的,用来屏蔽掉java程序在各种不同的硬件和操作系统对内存的访问的差异,这样就可以实现java程序在各种不同的平台上都能达到内存访问的一致性。可以避免像c++等直接使用物理硬件和操作系统的内存模型在不同操作系统和硬件平台下表现不同,比如有些c/c++程序可能在windows平台运行正常,而在linux平台却运行有问题。 8、web● 请谈一谈JSP有哪些内置对象?以及这些对象的作用分别是什么? JSP有9个内置对象:
● 请简要说明一下JSP和Servlet有哪些相同点和不同点?另外他们之间的联系又是什么呢? JSP 是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是”类servlet”。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑 Netty和Tomcat 最大的区别就在于通信协议,Tomcat是基于Http协议的,他的实质是一个基于http协议的web容器,但是Netty不一样,他能通过编程自定义各种协议,因为netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能,这就是netty和tomcat最大的不同。 ● 请谈谈你对Javaweb开发中的***的理解? ***模型涉及以下三个对象, (1)事件:用户对组件的一个操作,称之为一个事件 执行顺序: 1、给事件源注册*** ● 请问过滤器有哪些作用?以及过滤器的用法又是什么呢? 过滤器(filter)是从Servlet 2.3规范开始增加的功能,对Web应用来说,过滤器是一个驻留在服务器端的Web组件,它可以截取客户端和服务器之间的请求与响应信息,并对这些信息进行过滤。当Web容器接受到一个对资源的请求时,它将判断是否有过滤器与这个资源相关联。如果有,那么容器将把请求交给过滤器进行处理。在过滤器中,你可以改变请求的内容,或者重新设置请求的报头信息,然后再将请求发送给目标资源。 ● 请回答一下servlet的生命周期是什么。servlet是否为单例以及原因是什么? Servlet 通过调用 init () 方法进行初始化。 Servlet 调用 service() 方法来处理客户端的请求。 Servlet 通过调用 destroy() 方法终止(结束)。 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。 Servlet单实例,减少了产生servlet的开销; ● 请你说说,cookie 和 session 的区别? 1、cookie数据存放在客户的浏览器上,session数据放在服务器上。 2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。 3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE。 4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。 ● 说说你对get和post请求,并且说说它们之间的区别? ①get请求用来从服务器上获得资源,而post是用来向服务器提交数据; ● 请谈谈,转发和重定向之间的区别? forward是容器中控制权的转向,是服务器请求资源,服务器直接访问目标地址的URL,把那个URL 的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。 redirect就是服务器端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,因此从浏览器的地址栏中可以看到跳转后的链接地址,很明显redirect无法访问到服务器保护起来资源,但是可以从一个网站redirect到其他网站。forward更加高效,在有些情况下,比如需要访问一个其它服务器上的资源,则必须使用重定向 解决session共享问题 方法一、使用Nginx让它绑定ip,配置Nginx。 方法二、使用spring session+redis的方法解决session共享问题 9、电商项目1、跨域?当一个资源去访问另一个不同域名或者同域名不同端口的资源时,就会发出跨域请求。如果此时另一个资源不允许其进行跨域资源访问,那么访问的那个资源就会遇到跨域问题。 因为跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是于当前页同域名的路径,这能有效的阻止跨站攻击。 2、异步查询工具axios异步查询数据,自然是通过ajax查询,大家首先想起的肯定是jQuery。但jQuery与MVVM的思想不吻合 3、解决跨域问题的方案Jsonp:最早的解决方案,利用script标签可以跨域的原理实现。缺点:需要服务的支持、只能发起GET请求 nginx反向代理:利用nginx反向代理把跨域为不跨域,支持各种请求方式。缺点:需要在nginx进行额外配置 CORS(跨域资源共享):规范化的跨域请求解决方案,安全可靠。 优势:在服务端进行控制是否允许跨域,可自定义规则、支持各种请求方式 缺点:会产生额外的请求 同源策略 是浏览器的安全策略。是一种约定,是浏览器最核心最基本的安全功能。如果没有同源策略,浏览器很容易收到XSS,CSRF攻击。保证用户信息安全,防止恶意网站窃取数据 同源指“协议+域名(主机)+端口”三者相同。任一不同,都属于非同源。即使不同域名对应同一IP地址也非同源。 4、服务治理(SOA) 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键 服务治理要做什么?
5、远程调用方式无论是微服务还是SOA,都面临着服务间的远程调用。常见的远程调用方式有以下几种:
微服务,更加强调的是独立、自治、灵活。而RPC方式的限制较多,因此微服务框架中,一般都会采用基于Http的Rest风格服务。 6、Nginxnginx可以作为web服务器,但更多的时候,我们把它作为网关,因为它具备网关必备的功能: 反向代理、负载均衡、动态路由、请求过滤。 Web服务器分2类:
区分:web服务器不能解析jsp等页面,只能处理js、css、html等静态资源。 nginx作为反向代理 什么是反向代理?
nginx可以当做反向代理服务器来使用:
10、数据结构与算法1、哈希HashMap的底层实现
HashMap底层是数组和链表的结合。HashMap通过key的HashCode经过扰动函数处理过后得到Hash HashMap基于哈希思想,实现对数据的读写。当我们将键值对传递给put()方法时,它调用 键对象的hashCode()方法来计算hashcode,然后后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表 来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。HashMap在每个 链表节点中储存键值对对象。当两个不同的键对象的hashcode相同时,它们会储存在同一个 bucket位置的链表中,可通过键对象的equals()方法用来找到键值对。如果链表大小超过阈 值( 8),链表就会被改造为树形结构。 JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树,以减少搜索时间。 (一个是链表的长度达到8个,一个是数组的长度达到64个) 那为什么选择8才会选择使用红黑树呢 为了配合使用分布良好的hashCode,树节点很少使用。并且在理想状态下,受随机分布的hashCode影响,链表中的节点遵循泊松分布,而且根据统计,链表中节点数是8的概率已经接近千分之一,而且此时链表的性能已经很差了。所以在这种比较罕见和极端的情况下,才会把链表转变为红黑树。因为链表转换为红黑树也是需要消耗性能的,特殊情况特殊处理,为了挽回性能,权衡之下,才使用红黑树,提高性能。也就是大部分情况下,hashmap还是使用的链表,如果是理想的均匀分布,节点数不到8,hashmap就自动扩容 哈希冲突:如果两个不同对象的hashCode相同,这种现象称为hash冲突。 有以下的方式可以解决哈希冲突:
● 请你说明HashMap和Hashtable的区别? HashMap和Hashtable都实现了Map接口,因此很多特性非常相似。但是,他们有以下不同点: HashMap和TreeMap的区别 ● 请你说明一下TreeMap的底层实现? TreeMap 的实现就是红黑树数据结构,一棵自平衡的排序二叉树,这样就可以保证当需要快速检索指定节点。 红黑树的插入、删除、遍历时间复杂度都为O(lgN),所以性能上低于哈希表。但是哈希表无法提供键值对的有序输出,红黑树因为是排序插入的,可以按照键的值的大小有序输出。红黑树性质: 2、树红黑树的性质: 1.节点是红色或黑色。 2.根节点是黑色。 3.每个叶子节点都是黑色的空节点(NIL节点)。 4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点) 5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。 平衡二叉树的性质: 它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。 区别: 1、红黑树放弃了追求完全平衡,追求大致平衡,在与平衡二叉树的时间复杂度相差不大的情况下,保证每次插入最多只需要三次旋转就能达到平衡,实现起来也更为简单。 2、平衡二叉树追求绝对平衡,条件苛刻,实现起来比较麻烦,每次插入新节点之后需要旋转的次数不能预知。 4、链表● 请说明ArrayList和LinkedList的区别? ArrayList和LinkedList都实现了List接口,他们有以下的不同点: ● 请你讲讲数组(Array)和列表(ArrayList)的区别?什么时候应该使用Array而不是ArrayList? Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。 Array大小是固定的,ArrayList的大小是动态变化的。 ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。 对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。 5、数组6、排序7、堆与栈8、队列9、高级算法11、分布式分布式锁的几种常用实现方式 分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者做出取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性 针对分布式锁的实现,目前比较常用的有以下几种方案:
什么是分布式文件系统: 为什么要使用RPC?组成部分? 在一个典型RPC的使用场景中,包含了服务发现、负载、容错、网络传输、序列化等组件,而RPC的主要目标是更容易地构建分布式应用。为实现该目标,RPC框架需提供一种透明调用机制,让使用者不必显式的区分本地调用和远程调用。 1 、服务寻址2 、序列化和反序列化3 、网络传输 12、Linux部署项目用到的linux命令: 1.进入tomcat的bin目录 cd /data/apache-tomcat-6.0.39/bin 2.查看tomcat的进程 ps -ef | grep tomcat 3.杀死进程 kill -9 + 进程数 查看进程 2.1、ps -ef | grep xx 2.2、ps -aux | grep xxx(-aux显示所有状态) 查看端口:1、netstat -anp | grep 端口号(状态为LISTEN表示被占用) 4.启动项目 sh startup.sh 5.永久删除文件 rm -rf 文件 6.复制文件 cp -Rf 原路径/ 目的路径/ 7.压缩文件夹 解压:tar zxvf FileName.tar.gz 8.解压(安装zip命令)* unzip 压缩包 9.移动 mv +路径/文件 +要移到的路径 9.从本机复制文件到远程 scp -r ROOT root@192.168.1.1:/data/apache-tomcat-6.0.39/webapps scp -r 目录名 远程计算机用户名@远程计算机的ip:远程计算机存放该目录的路径 13、并发编程进程与线程的区别: 1、进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位) ● 如何保证线程安全? 通过合理的时间调度,避开共享资源的存取冲突。另外,在并行任务设计上可以通过适当的策略,保证任务与任务之间不存在共享资源 ● 线程同步和线程调度的相关方法。 - wait():使一个线程处于等待状态,并且释放所持有的对象的锁; - sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理异常; - notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关; - notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态; *● Java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? * 有四种实现方法,分别是继承Thread类与实现Runnable接口,使用Callable和Future创建线程、使用线程池例如用Executor框架。 ● 启动一个线程是用run()还是start()? 启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。 ● 请说明一下sleep() 和 wait() 有什么区别? sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,把执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。 ● 请分析一下同步方法和同步代码块的区别是什么? 区别:同步方法默认用this或者当前类class对象作为锁; 同步代码块可以选择以什么来加锁,比同步方法要更细颗粒度,可以选择只同步会发生同步问题的部分代码而不是整个方法。 ● 请详细描述一下线程从创建到死亡的几种状态都有哪些?
● 请问什么是死锁(deadlock)? 两个线程或两个以上线程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是这些线程都陷入了无限的等待中。如何避免线程死锁? ● JAVA中如何确保N个线程可以访问N个资源,但同时又不导致死锁? 使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。 常用线程池,线程池有哪几个参数 Java通过Executors提供四种线程池,分别为: 4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 参数 maximumPoolSize :线程最大线程数 workQueue :阻塞队列,存储等待执行的任务 很重要 会对线程池运行产生重大影响 keepAliveTime :线程没有任务时最多保持多久时间终止 unit :keepAliveTime的时间单位 threadFactory :线程工厂,用来创建线程 rejectHandler :当拒绝处理任务时的策略 线程池怎么用
● Synchronized和lock synchronized当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成F死锁现象,因此使用Lock时需要在finally块中释放锁;Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。 ● Syncronized锁,如果用这个关键字修饰一个静态方法,锁住了什么?如果修饰成员方法,锁住了什么? synchronized修饰静态方法以及同步代码块的synchronized (类.class)用法锁的是类,线程想要执行对应同步代码,需要获得类锁。 synchronized修饰成员方法,线程获取的是当前调用该方法的对象实例的对象锁。 synchronized 和 CAS 的区别
CAS 是比较并替换。它当中使用了3个基本操作数:内存地址 V,旧的预期值 A,要修改的新值 B。采用的是一种乐观锁的机制,它不会阻塞任何线程,所以在效率上,它会比 所以,在并发量非常高的情况下,我们尽量的用同步锁,而在其他情况下,我们可以灵活的采用 CAS 机制。 synchronized关键字和volatile关键字比较:
线程池运行原理分析 1、创建一个线程池,在还没有任务提交的时候,默认线程池里面是没有线程的。也可以调用prestartCoreThread方法,来预先创建一个核心线程。 ● 请说明一下线程池有什么优势? 第一:降低资源消耗。第二:提高响应速度。第三:提高线程的可管理性 线程池的运行流程 首先判断核心线程池里的线程是否都在执行任务,如果不是则直接从核心线程池中创建一个线程来执行,如果都在忙则判断任务队列是否也满了,没满的话将任务放进去等待执行,满了就判断线程池的全部线程是否都在忙,如果都在忙就交给饱和策略来处理,否则就创建一个线程来帮助核心线程处理任务。 线程阻塞
AQS原理 抽象的队列式同步器,是除了java自带的synchronized关键字之外的锁机制,AQS的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资源设置为锁定状态,如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。 14、JVM
主内存:多个线程共享的内存,方法区和堆属于主内存区域。线程工作内存:每个线程独享的内存。虚拟机栈、本地方法栈、程序计数器属于线程独享的工作内存 Java创建对象的过程: ● JVM加载class文件的原理是什么? JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个Java运行时系统组件。它负责在运行时查找和装入类文件的类。 Java中的所有类都需要由类加载器装载到JVM中才能运行。类加载器的工作就是把class文件从硬盘读取到内存中。 双亲委派机制: 如果一个类加载器收到了类加载请求,他并不会自己先去加载,而是把这个请求委托给父类的加载器去执行; 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终达到顶层的启动类加载器 如果父类加载器可以完成类加载任务就成功返回,如果父类加载器不能完成加载任务,子加载器互尝试自己去加载 堆内存的分配策略: 1对象优先在eden区分配,Eden区没有足够的空间,将触发一次Minor GC。 2大对象直接进入老年代(为了避免为大对象分配内存时由于分配担保机制带来的复制而降低效率 ), 3长期存活的对象进入老年代 4动态对象年龄判断:如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入到老年代,无需等到MaxTenuringThreshold中要求的年龄 5空间分配担保:-XX: HandlePromotionFailure Minor GC与Full GC分别在什么时候发生? 触发MinorGC(Young GC) 虚拟机在进行minorGC之前会判断老年代最大的可用连续空间是否大于新生代的所有对象总空间 1、如果大于的话,直接执行minorGC 2、如果小于,判断是否开启HandlerPromotionFailure,没有开启直接FullGC 3、如果开启了HanlerPromotionFailure, JVM会判断老年代的最大连续内存空间是否大于历次晋升的大小,如果小于直接执行FullGC 触发FullGC
Minor GC 和 Full GC 有什么不同呢? 分代收集器: 老生代和新生代两个区域,而新生代又会分为:Eden 区和两个 Survivor区(From Survivor、To Survivor) 为什么 Survivor 分区不能是 0 个? 如果 Survivor 是 0 的话,也就是说新生代只有一个 Eden 分区,每次垃圾回收之后,存活的对象都会进入老生代,这样老生代的内存空间很快就被占满了,从而触发最耗时的 Full GC ,显然这样的收集器的效率是我们完全不能接受的。 为什么 Survivor 分区不能是 1 个? 如果 Survivor 分区是 1 个的话,假设我们把两个区域分为 1:1,那么任何时候都有一半的内存空间是闲置的,显然空间利用率太低不是最佳的方案。但如果设置内存空间的比例是 8:2 ,只是看起来似乎“很好”,假设新生代的内存为 100 MB( Survivor 大小为 20 MB ),现在有 70 MB 对象进行垃圾回收之后,剩余活跃的对象为 15 MB 进入 Survivor 区,这个时候新生代可用的内存空间只剩了 5 MB,这样很快又要进行垃圾回收操作,显然这种垃圾回收器最大的问题就在于,需要频繁进行垃圾回收。 为什么 Survivor 分区是 2 个? 如果 Survivor 分区有 2 个分区,我们就可以把 Eden、From Survivor、To Survivor 分区内存比例设置为 8:1:1 ,那么任何时候新生代内存的利用率都 90% ,这样空间利用率基本是符合预期的。再者就是虚拟机的大部分对象都符合“朝生夕死”的特性,所以每次新对象的产生都在空间占比比较大的 Eden 区,垃圾回收之后再把存活的对象方法存入 Survivor 区,如果是 Survivor 区存活的对象,那么“年龄”就 +1 ,当年龄增长到 15 (可通过设定)对象就升级到老生代。 ● 请说明一下垃圾回收的优点以及原理 使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。不再会被使用的对象的内存不能被回收,就是内存泄露 判断对象是否可回收的方法 引用计数法:给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的 可达性分析法:通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过 强引用、软引用、弱引用、虚引用(虚引用与软引用和弱引用的区别、软引用能带来的好处) 1.强引用 2.软引用 如果一个对象只具有软引用,那就类似于可有可无的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如 3.弱引用 如果一个对象只具有弱引用,那就类似于可有可无的生活用品。弱引用与软引用的区别在:只具有弱引用的对象 4.虚引用 虚引用主要用来跟踪对象被垃圾回收的活动 ,在程序设计中一般很少使用弱引用与虚引用,使用软引用的情况较多,因为软引用可以加速 JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出等问题的产生** 如何判断一个常量是废弃常量 如何判断一个类是无用的类 垃圾回收算法: 1、标记-清除算法 2、复制算法 3、标记-整理算法 4、分代收集算法 垃圾收集器 1、 Serial 收集器 它的 “单线程” 的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程,直到它收集结束。 新生代采用复制算法,老年代采用标记-整理算法 2、ParNew 收集器其实就是 Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样 3 、Parallel Scavenge 收集器它关注点是吞吐量(高效率的利用 CPU)。CMS 等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)。 新生代采用复制算法,老年代采用标记-整理算法。 4、Serial Old 收集器,它是一个单线程收集器。它主要有两大用途:一种用途是在 JDK1.5 以及以前的 5 、Parallel Old 收集器 6 、CMS 收集器,是一种以获取最短回收停顿时间为目标的收集器。它而非常符合在注重用户体验的应用上使用。CMS(Concurrent Mark Sweep)收集器是 HotSpot 虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作 7、G1 收集器是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满 volatile的作用 保证共享变量的可见性:使用volatile修饰的变量,任何线程对其进行操作都是在主内存中进行的,不会产生副本,从而保证共享变量的可见性。防止局部指令重排序:happens-before规则中的volatile变量规则规定了一个线程先去写一个volatile变量,然后一个线程去读这个变量,那么这个写操作的结果一定对读的这个线程可见。volatile如何防止指令重排序 volatile是通过内存屏障来防止指令重排序的。volatile防止指令重排序具体步骤: 在每个volatile写操作的前面插入一个StoreStore屏障。在每个volatile写操作的后面插入一个StoreLoad屏障。在每个volatile读操作的后面插入一个LoadLoad屏障。在每个volatile读操作的后面插入一个LoadStore屏障。 15、项目认证授权是如何实现的? Spring security + Oauth2完成用户认证及用户授权。认证授权流程如下: 认证与授权实现思路 如果系统的模块多,每个模块都需要就行授权与认证,所以选择基于token的形式进行授权与认证,用户根据用户名密码认证成功,然后获取当前用户角色的一系列权限值,并以用户名为key,权限列表为value的形式存入redis缓存中,根据用户名相关信息生成token返回,浏览器将token记录到cookie中,每次调用api接口都默认将token携带到header请求头中,Spring-security解析header头获取token信息,解析token获取当前用户名,根据用户名就可以从redis中获取权限列表,这样Spring-security就能够判断当前请求是否有权限访问 使用rabbitMQ 1、平台包括多个站点,页面归属不同的站点,需求是发布一个页面应将该页面发布到所属站点的服务器上。 分布式事务: 1、在微服务中使用Spring 声明式事务控制方式进行控制,在Service方法上添加@Transctional注解即可实现事务 项目中课程搜索采用ElasticSearch来完成。实现方法是: 系统对异常的处理使用统一的异常处理流程。 http协议处理视频流 你在开发中遇到什么问题?是怎么解决的? 例子: 例子: Redis服务器 can not get resource from pool. 1000个线程并发还能跑,5000个线程的时候出现这种问题,查后台debug日志,发现redis 线程池不够。刚开始设置的是: 解决:顺便也改了一下jdbc 的连接池参数,最大空闲和最大连接数都改成1000.在测一下。可以 例子: 注册中心和服务提供者集群注册失败,启动报错 解决:修改yml文件,修改启动类上的注解,yml文件缩进出了问题,服务端启动类上应该添加注解@EnableEurekaServer,客户端@EnableDiscoveryClient 例子: xml文件配置错误,页面访问一直无数据 解决:根据浏览器的开发工具,定位错误,检查xml文件的SQL,namespace,parameterType等是否正确,是否假如应有的注解 例子: git合并冲突,甲乙都是根据point.java文件进行开发,甲开发出来版本2,并且提交了代码,乙开发出来版本3,也需要提交代码,此时将会报错存在冲突。因为甲提交版本之后,此时远端的代码已经是版本2了,而乙是在版本1的基础上进行开发出了版本3,所以乙想要提交代码,势必要将自己的代码更新为版本2的代码,然后在进行提交 解决:拉去远端代码,存在冲突,会报错。此时我们需要将本地代码暂存起来stash;更新本地代码,将本地代码版本更新和远端的代码一致,将暂存的代码合并到更新后的代码后,有冲突的要手动解决冲突,然后提交解决冲突后的代码。Git<resolve conflict 例子: 支付接口采用微信的扫码支付拿到需求后,首先去阅读微信的接口文档,重点阅读统一下单、支付结果通知、支付结果查询三个接口。下载官方提供的sdk编写单元测试用例测试每个接口。测试时没有使用微信的沙箱测试,直接使用正式接口,将金额改的小一些进行测试。单元测试通过后开发整个支付功能,最终集成测试通过。 解决:订单支付接口参数的签名问题,当时是因为自己没有仔细看接口文档导致少写一个必填参数一直报签名失败,随后将所有必填参数填写完成,最终解决问题。 例子: 一个接口出现Bug你是怎么调试的? |
|
来自: 新用户5605YaM3 > 《待分类》