ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

JAVA八股文面试题

JAVA八股文面试题 1. JDK、JRE、JVM之间的区别jdk包含jrejre包含jvm。jvm是java实现整个跨平台最核心的部分负责运行字节码文件jre中则还包括一些jvm运行时需要的类库jdk中则还包括java编译器。2. 面向对象a.封装封装的意义在于明确标识出允许外部使用的所有成员函数和数据项内部细节对外部调用透明外部调用无需修改或者关心内部实现b.继承继承基类的方法并做出自己的改变和/或扩展子类共性的方法或者属性直接使用父类的而不需要自己再定义只需扩展自己个性化的c.多态基于对象所属类的不同外部对同一个方法的调用实际执行的逻辑不同3. final关键字的作用a.修饰类表示类不可被继承b.修饰方法表示方法不可被子类覆盖但是可以重载c.修饰变量表示变量一旦被赋值就不可以更改它的值。d.修饰成员变量如果final修饰的是类变量只能在静态初始化块中指定初始值或者声明该类变量时指定初始值。如果final修饰的是成员变量可以在非静态初始化块、声明该变量或者构造器中执行初始值。e.修饰局部变量系统不会为局部变量进行初始化局部变量必须由程序员显示初始化。因此使用final修饰局部变量时即可以在定义时指定默认值后面的代码不能对变量再赋值也可以不指定默认值而在后面的代码中对final变量赋初值仅一次f.修饰基本类型数据和引用类型数据如果是基本数据类型的变量则其数值一旦在初始化之后便不能更改如果是引用类型的变量则在对其初始化之后便不能再让其指向另一个对象。但是引用的值是可变的。4. hashCode()与equals()之间的关系如果比较两个对象通常先调用hashCode()方法获取两个对象的哈希值进行对比若值不同对象肯定不同若值相同则会进一步调用equals()方法来最终确定两个对象是不是相等的。5. String、StringBuffer、StringBuilder的区别string是不可变的如果尝试修改会生成新的字符串对象StringBuffer和StringBuilder则是可变的 而且前者线程安全后者线程不安全所以单线程环境下StringBuilder效率更高。6. 泛型中extends和super的区别extends和super是用来限定泛型类型参数的关键字。前者声明一个上界限定传入的类型必须是该类型或其子类后者声明一个下界限定传入的类型必须是该类型或其父类。7. 和equals方法的区别如果是基本数据类型则比较他们的值如何是引用类型比较的是他们的引用地址。equals具体要看各个类重写equals方法后的比较逻辑比如string类虽然是引用类型但是重写后比较的是字符串中各个字符是否全部相等。8. 重载和重写的区别重载是方法名一样参数列表不同重写是方法名一样参数列表一样返回类型一样但方法体不一样但要注意子类方法的访问修饰权限不能小于父类。9. 接口和抽象类的区别a.抽象类可以存在普通成员函数而接口中只能存在public abstract 方法。b.抽象类中的成员变量可以是各种类型的而接口中的成员变量只能是public static final类型的。c.抽象类只能继承一个接口可以实现多个。10. List和Set的区别List有序按对象插入的顺序保存对象可重复允许多个null元素对象可以使用迭代器Iterator取出所有元素再逐一遍历还可以使用getint index获取指定下标的元素。Set无序不可重复最多允许有一个null元素对象取元素时只能使用迭代器Iterator取出所有元素再逐一遍历。11. ArrayList的底层工作原理a.在构造ArrayList时如果没有指定容量那么内部会构造一个空数组如果指定了容量则会构造一个特定容量大小的数组。b.在添加元素时会先判断数组容量是否足够不够则会按照1.5倍扩容容量够了后才会添加该元素。c.在添加元素时如果指定了下标则先检查下标是否越界再确认数组容量是否足够不够则1.5倍扩然后再将新元素添加到该下标如果该位置后面还有元素则元素后移。d.在获取指定下标元素时先判断下标是否越界然后从数组中取出该位置元素。12. ArrayList和LinkedList区别a.底层数据结构不同ArrayList是数组LinkedList是链表。b.适用场景不同ArrayList更适合随机查找LinkedList更适合添加和删除两者的各个操作下的时间复杂度不同c.ArrayList和LinkedList都实现了list接口但是LinkedList还实现了Deque(双端队列)接口所以后者还能当队列使用。13. HashMap和HashTable有什么区别其底层实现原理是什么区别a.HashMap方法没有synchronized修饰线程非安全HashTable线程安全。b.HashMap允许key和value为nullHashTable不允许。底层实现数组链表jdk8开始链表高度到8、数组长度超过64链表转为红黑树元素内部以Node接点来存储若后续长度低于6则重新转为链表。key为null时存在下标为0的地方。14. ConcurrentHashMap是什么ConcurrentHashMap 是 Java 并发包 java.util.concurrent 中提供的线程安全、高并发的哈希表实现实现了 ConcurrentMap 接口继承 AbstractMap。它用于在多线程环境下替代 HashMap 和 Hashtable在保证线程安全的同时提供更高的并发性能。15. ConcurrentHashMap与HashMap、Hashtable、Collections.synchronizedMap 的区别16. 谈谈ConcurrentHashMap的扩容机制1.7版本a. 1.7版本的ConcurrentHashMap是基于Segment分段实现的b. 每个Segment相对于一个小型的HashMapc. 每个Segment内部会进行扩容和HashMap的扩容逻辑类似d. 先生成新的数组然后转移元素到新数组中e. 扩容的判断也是每个Segment内部单独判断的判断是否超过阈值1.8版本a. 1.8版本的ConcurrentHashMap不再基于Segment实现b. 当某个线程进行put时如果发现ConcurrentHashMap正在进行扩容那么该线程一起进行扩容c. 如果某个线程put时发现没有正在进行扩容则将key-value添加到ConcurrentHashMap中然后判断是否超过阈值超过了则进行扩容d. ConcurrentHashMap是支持多个线程同时扩容的e. 扩容之前也先生成一个新的数组f. 在转移元素时先将原数组分组将每组分给不同的线程来进行元素的转移每个线程负责一组或多组的元素转移工作17. 深拷贝和浅拷贝深拷贝和浅拷贝就是指对象的拷贝一个对象中存在两种类型的属性一种是基本数据类型一种是实例对象的引用。a. 浅拷贝是指只会拷贝基本数据类型的值以及实例对象的引用地址并不会复制一份引用地址所指向的对象也就是浅拷贝出来的对象内部的类属性指向的是同一个对象b. 深拷贝是指既会拷贝基本数据类型的值也会针对实例对象的引用地址所指向的对象进行复制深拷贝出来的对象内部的属性指向的不是同一个对象18. CopyOnWriteArrayList的底层原理是怎样的a. 首先CopyOnWriteArrayList内部也是通过数组来实现的在向CopyOnWriteArrayList添加元素时会复制一个新的数组写操作在新数组上进行读操作在原数组上进行b. 并且写操作会加锁防止出现并发写入丢失数据的问题c. 写操作结束之后会把原数组指向新数组d. CopyOnWriteArrayList允许在写操作时来读取数据大大提高了读的性能因此适合读多写少的应用场景但是CopyOnWriteArrayList会比较占内存同时可能读到的数据不是实时最新的数据所以不适合实时性要求很高的场景19. 如何实现一个IOC容器a.配置文件配置包扫描路径b.递归包扫描获取.class文件c.反射、确定需要交给IOC管理的类d.对需要注入的类进行依赖注入20. 什么是字节码采用字节码的好处在java中供虚拟机理解的代码叫做字节码即扩展名为.class的文件。java语言通过字节码的方式不仅提高程序的执行效率而且还保持了解释型语言可移植的特点。21. java类加载器jdk自带的有三个类加载器AppClassLoader:自定义加载器的父类负责加载classpath下的类文件。ExtClassLoader:是AppClassLoader的父类加载器负责加载%JAVA_HOME%/lib/ext文件夹下的jar包和class类。bootstrap ClassLoader是ExtClassLoader的父类加载器默认负责加载%JAVA_HOME%/lib文件夹下的jar包和class类。22. 双亲委托模型向上委派向下查找。实际上就是查找缓存是否加载了该类有直接返回没有则继续向上委派到顶层之后如果还是没有则到加载路径中查找有则加载返回没有则向下查找一直查到发起加载的加载器为止。23. Java中的异常java中的所有异常都来自顶级父类Throwable。Throwable下有两个子类Exception和Error。Error是程序无法处理的错误一旦出现则程序被迫停止。Exception不会导致程序停止其又分为RunTimeException运行时异常和CheckedException检查异常前者会导致当前线程执行失败后者导致程序编译不通过。24. GC如何判断对象可以被回收a.引用计数法每个对象都有一个引用计数属性每新增一个引用加1反之减1当为0时回收。b.可达性分析法从GC Roots开始向下搜索其路径为引用链。当一个对象到GC Roots没用任务引用链项相连则表明其不可用可以回收。25. 线程的生命周期及状态a.创建New新创建了一个线程对象。b.就绪Runable线程对象创建后其他线程调用了该对象的start方法。改状态的线程位于线程池中变得可运行等待获取cpu的使用权。c.运行Running就绪状态的线程获取了cpu执行程序代码。d.阻塞Blocked线程因为某种原因放弃cpu使用权暂停运行。知道线程进入就绪状态才有机会继续运行。e.死亡Dead线程执行完毕或因特殊原因结束了run方法该线程结束生命周期。26. sleep、wait、join、yield区别a.sleep是Thread类的静态方法wait则是object类的本地方法。b.sleep不会释放lock但是wait会释放并加入到等待池中。c.sleep不依赖synchronized但是wait需要依赖。d.sleep不需要被唤醒wait需要。e.sleep会让出cpu并强制上下文切换但wait不一定。f.yield执行后线程直接进入就绪状态释放cpu的执行权但仍保留执行资格。g.join执行后线程进入阻塞状态。27. 对线程安全的理解当多个线程访问一个对象时如果不进行额外的同步控制或其他的协调操作调用这个对象的行为都可以获得正确的结果就可以说这个对象是线程安全的。28. 对守护线程的理解为所有非守护线程提供服务的线程。其应用场景如下a.为其他线程提供服务支持的情况。最经典的就是GC垃圾回收线程。b.在任何情况下当程序结束这个线程必须正常且立刻关闭就能当做守护线程。29. ThreadLocal原理及使用场景ThreadLocal 是一个线程级别变量每个线程都有一个独立的 ThreadLocal 在并发模式下是绝对安全的变量。使用场景a.在进行对象夸层传递的时候使用Threadlocal可以避免多次传递打破层次间的约束。b.线程间数据隔离。c.进行事物操作用来存储事务信息。d.数据库连接Session回话管理。30. ThreadLocal内存泄漏原因如何避免根源由于ThreadLocalMap的生命周期和Thread一样长如果没有手动的清除对应key就会导致内存泄漏而不是因为弱引用。正确使用方法a.每次使用完ThreadLocal都调用它的remove方法清除数据。b.将ThreadLocal的变量定义为priivate static 这样就一直存在Threadlocal的强引用也就能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的value值进而清除掉。31. 并发、并行、串行区别a.并发允许两个任务彼此干扰。统一时间点只有一个任务运行交替执行。b.并行在时间上是重叠的两个任务在同一时刻互不干扰的同时执行。c.串行在时间上不可能发生重叠前一个任务没搞定下一个任务只能等待。32. 并发的三大特性a.原子性在一个操作中cpu不可以在中途暂停然后再调度即不被中断要不全部执行完成要不都不执行。b.可见性当多个线程访问同一个变量时一个线程修改了这个变量的值其他线程能够立即看得到修改的值。c.有序性程序执行的顺序按照代码的先后顺序执行。使用synchronized关键字可以解决以上三个问题的出现。33. 为什么使用线程池解释线程池的参数原因a.降低资源消耗。提高线程利用率降低线程创建和销毁的消耗。b.提高响应速率。任务来了直接有线程可以使用而不是先创建再执行。c.提高线程的可管理性。线程是稀缺资源使用线程池可以统一分配调优监控。参数corePoolSize:核心线程数其创建后不会被消除属于常驻线程。maxnumPoolSize最大线程数表示最大允许被创建的线程数。keepAliveTime、unit超出核心线程之外的线程的空闲存活时间可以通过setKeepAliveTime来设置空闲时间。workQueue用来存放待执行的任务。当核心线程都已被使用还有任务进来则全部放入队列中直到队列满后任务若还在继续就会创建新的线程。ThreadFactory线程工厂用来生产线程执行任务。Handler任务拒绝策略。有两种情况第一调用shutdown等方法关闭线程池后即使其中还有未完成的任务但此时想提交任务就会遭到拒绝第二已达到最大线程数线程池没有能力处理新提交的任务也会拒绝。34. 线程池中阻塞队列的作用为什么是先添加队列而不是先创建最大线程作用a.普通的队列只能作为一个长度有限的缓冲区如果超出其长度就无法保存该任务但是阻塞队列可以通过阻塞保留住当前想要继续加入的任务。b.阻塞队列自带注射唤醒功能可以保证任务队列中没有任务时阻塞获取任务的线程使得线程进入wait状态释放cpu资源。原因在创建新线程的时候是要获取全局锁的这个时候其它的就得阻塞影响了整体效率。35. 线程池中线程复用原理线程池将线程和任务进行解耦线程是线程任务是任务摆脱了之前通过Thread创建线程时的一个线程必须对应一个任务的限制而是让每个线程去执行一个“循环任务”不停的检查是否有任务需要被执行有则调用任务中的run方法。36. spring是什么Spring是一个轻量级的控制反转IOC和面向切面AOP的容器框架。37. 谈谈对AOP的理解将程序中的交叉业务逻辑比如安全、日志、事务等封装成一个切面然后注入到目标对象具体业务逻辑中去。AOP可以对某个对象或某些对象的功能进行增强可以在执行某个方法之前或之后额外做一些事情。38. 谈谈对IOC的理解实际上就是一个容器mapkey-value存储配置文件里的bean节点、类似component注解的类对象在项目启动时通过反射读取配置文件里的bean节点及注解类创建对象放入map中。在没有引入IOC时对象A依赖B在A初始化或运行中必须主动创建B或使用已有的B但引入IOC后当A需要B时IOC容器会主动创建B获得依赖对象的过程由自身管理变为了由IOC容器主动注入这就是控制反转和依赖注入。39. BeanFactroy和ApplicationContext的区别ApplicationContext是BeanFactroy的子接口提供了更完整的功能a.继承了MessageSource因此支持国际化。b.统一的资源文件访问方式。c.提供在监听中注册bean的事件。d.同时加载多个配置文件。e.载入多个有继承关系上下文使得每个上下文都专注于一个特定的层次比如应用的web层。区别a.BeanFactroy采用的是延迟加载来注入Bean的即只有用到了某个Bean时才进行加载实例化ApplicationContext则是在容器启动时一次性创建所有的Bean但是后者相对占用内存如果配置的Bean较多程序启动会很慢。b.BeanFactroy通常以编程的方式被创建ApplicationContext还能以声明的方式创建如使用ContextLoader。c.BeanFactroy和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用但是前者需要手动注册后者则是自动注册。40. 描述一下SpringBean的生命周期a.解析类得到BeanDefinition。b.如果有多个构造方法则要推断构造方法。c.确定好构造方法后进行实例化得到一个对象。d.对对象中加了Autowired注解的属性进行填充。e.回调Aware方法比如BeanNameAware、BeanFactoryAware。f.调用BeanPostProcessor的初始化前的方法。g.调用初始化方法。h.调用BeanPostProcessor的初始化后的方法在这里会进行AOP。i.如果当前创建的Bean是单例的则会把bean放入单例池。j.使用bean。k.Spring容器关闭时调用DisposableBean中的destory方法。41. 解释下Spring支持的几种bean的作用域a.单列Singleton:默认每个容器中只有一个bean实例。b.原型Prototype为每一个bean请求提供一个实例。c.请求Requestbean被定义为在每个http请求中创建一个单例对象也就是说单个请求中都会复用这一个单例对象。d.会话Session确保每个session中有一个bean实例在session过期后bean会随之失效。e.全局会话GlobalSession在Portlet环境下使用代表全局会话的Bean。42. Spring中的单例bean是线程安全的吗不是线程安全的框架并没有对bean进行多线程的封装。最简便的就是改变bean的作用域为原型模式或者使用Threadlocal把变量变成线程私有的或者加锁。43. Spring框架中都用了哪些设计模式a.简单工厂spring中的BeanFactory就是简单工厂的体现根据传入的一个唯一标识来获得bean对象但是否是在传入参数后创建还是传入参数前创建要根据具体情况判断。b.工厂方法实现了FactoryBean接口的bean是一类叫做factory的bean特点是sping会在使用getBean调用获得改bean时会自动的调用bean.getObject方法返回的不是factory这个bean。c.单例模式保证一个类仅有一个实例并提供一个访问它的全局访问点。d.适配器模式Spring定义了一个适配器接口使得每一个Controller有一种对应的适配器实现类让适配器代替Controller执行相应的方法。e.装饰器模式动态的给一个对象添加一些额外的职责。f.动态代理、观察者模式、策略模式。44. Spring事务的实现方式和原理以及隔离级别实现方式编程式和申明式Transactional注解就是申明式的。原理在方法上加上Transactional注解就可以开启事务spring会就这个类生成一个代理对象当在使用这个代理对象的方法时如何这个方法上有Transactional注解那么代理逻辑会把事务的自动提交设置为false然后再去执行原本业务逻辑当其中没有出异常时代理逻辑就会把事务提交如果出现异常则会回滚。隔离级别spring的隔离级别就是数据库的隔离级别外加一个默认级别a.DEFAULT这是默认的隔离级别表示使用数据库默认的隔离级别。b.READ_UNCOMMITTED最低的隔离级别允许读取尚未提交的数据变更可能会导致脏读、不可重复读和幻读。c.READ_COMMITTED保证一个事务不能读取另一个事务已修改但未提交的数据可避免脏读但可能导致不可重复读和幻读。d.REPEATABLE_READ确保事务可以多次从一个字段读取相同的数据在事务处理过程中若该字段被其他事务更新该事务将不会检测到但是可以防止不可重复读和幻读。e.SERIALIZABLE最高的隔离级别所有事务串行化执行可以避免所有隔离问题但是性能最差。45. Spring事务传播机制a.required默认的如果当前没有事务则自己新建一个事务如果当前存在事务则加入这个事务。b.support当前存在事务则加入当前事务当前没有事务就以非事务执行。c.mandatory当前存在事务则加入不存在则抛异常。d.requirse_new创建一个新事务若存在当前事务则挂起当前事务。e.not_support以非事务方式执行若存在当前事务则挂起当前事务。f.never不使用事务若当前事务存在则抛异常。g.nested如果当前事务存在则在嵌套事务中执行否则required一样。46. Spring事务什么时候会失效Spring事务的原理是AOP失效就是AOP不起作用有以下几个原因a.发生自调用类里面使用this调用本类的方法。b.方法不是public的c.数据库不支持事务。d.没有被spring管理。e.异常被吃掉事务不会回滚或抛出的异常没有被定义默认为RuntimeException47. 什么的是bean的自动装配它有哪些方式bean的自动装配指的是bean的属性值在进行注入的时候通过某种特定的规则和方式去容器中查找并设置到具体的对象属性中定义“autowire”主要有五种方式:a.no 缺省情况下自动配置是通过“ref”属性手动设定在项目中最常用。b.byName 根据属性名称自动装配。如果一个bean的名称和其他bean属性的名称是一样的将会自装配它。c.byType 按数据类型自动装配如果bean的数据类型是用其它bean属性的数据类型兼容并自动装配它。e. constructor 在构造函数参数的byType方式。f.autodetect 如果找到默认的构造函数使用“自动装配用构造”; 否则使用“按类型自动装配”。48. SpringBoot、SpringMVC、Spring有什么区别Spring是一个IOC容器用来管理Bean使用依赖注入实现控制反转可以很方便的整合各种框架提供AOP机制。SpringMVC是Spring对web框架的一个解决方案提供了一个总的前段控制servlet用来接收请求然后定义了一套由路由及适配执行handle将handle结果使用视图解析技术生成视图展示给前端。SpringBoot是一个spring的一个快速开发工具包能够让程序员更方便、快捷的开发SpringSpringMVC应用简化了配置整合了一系列的解决方案可以开箱即用。49. SpringMVC工作流程a.用户发送请求至前端控制器DispatcherServlet。b.DispatcherServlet收到请求调用HandlerMapping处理器映射器。c.处理器映射器找到具体的处理器可以根据xml配置、注解进行查找生成处理器及处理拦截器如果有则生成一并返回给DispatcharServlet。d.DispatcharServlet调用HandleAdapter处理适配器。e.HandleAdapter经过适配器调用具体的处理器Controller也叫后端控制器f.Controller执行完成返回ModelandView。g.HandleAdapter将Controller执行结果ModelandView返回给DispatcherServlet。h.DispatcherServlet将ModelandView传给ViewResloer视图解析器。i.ViewResloer解析后返回具体的View。j.DispatcherServlet根据View进行渲染视图即将模型数据填充至视图中。k.DispatcherServlet响应用户。50. SpringBoot自动配置原理主要使用Import Configuration Srping spi实现自动配置类由各个starter提供使用Configuration Bean定义配置类放到MEAT-INF/spring.factories下使用Srping spi扫描MEAT-INF/spring.factories下的配置类使用Import导入自动配置类。​编辑51. mybatis的优缺点优点a.基于sql语句编程相当灵活不会对应用程序或者数据库的现有设计造成影响sql写在xml里面解除了sql与程序代码的耦合便于统一管理提供xml标签支持编写动态sql语句并可重用。b.与jdbc相比减少了%0%以上代码量不需要手动开关连接。c.很好的与各种数据库兼容。d.能够与spring很好的集成。e.提供映射标签支持对象与数据库ORM字段的关系映射提供对象关系映射标签支持对象关系组件维护。缺点a.sql语句的编写工作量大。b.sql语句依赖数据库导致数据库移植性差不能随意更换数据库。52. MyBatis和Hibernate有哪些不同a.开发速度Hibernate的真正掌握要比MyBatis难一些如果项目中基本没有用到复杂查询则用Hibernate会跟快一些反之则是MyBatis。b.开发工作量针对高级查询MyBatis要手动编写SQl语句而Hibernate可以更专注于业务流程。c.sql优化MyBatis可以更方便的优化sqlHibernate的查询会将所有字段查出这点会有性能消耗。d.对象管理Hibernate是完整的对象/关系映射解决方案提供了对象状态管理的功能而MyBatis需要用户对对象自己进行详细的管理。53. #{}和${}的区别#{}是预编译处理、是占位符${}是字符串替换、是拼接符。mybatis在处理#{}时会将sql中的#{}替换为调用PreparedStatement来赋值。mybatis在处理${}时会将sql中的#{}替换成变量的值调用Statement来赋值。#{}的替换是在DBMS中变量替换后#{}对应的变量自动加上单引号。${}的替换是在DBMS外变量替换后${}对应的变量不会加上单引号。使用#{}可以有效防止sql注入提高系统安全性。54. 索引的基本原理原理把无序的数据变成有序的查询。a.把创建了索引的列的内容进行排序。b.对排序结果生成倒排表。c.在倒排表内容上拼上数据地址链。d.在查询的时候先拿到倒排表内容再取出数据地址链从而拿到具体数据。55. myql聚簇和非聚簇索引的区别都是B树的结果。聚簇索引将数据存储与索引放到一起并且按照一定顺序组织。非聚簇索引叶子节点不存储数据存储的是数据行地址。56. mysql索引的数据结构各自优势索引的数据结构和具体存储引擎的实现有关在mysql中使用较多的索引有hash索引、B树索引等InnoDb存储引擎的默认索引实现为B树索引。对于哈希索引来说底层的数据结构就是哈希表因此在绝大多数需求为单条记录查询的时候可以选择哈希索引查询性能最快其余大部分场景建议选择B树索引。57. 索引设计的原则查询更快占用空间更小。a.适合索引的列是出现在where子句中的列或者连接子句中指定的列。b.基数较小的类没必要在此列建索引。c.使用短索引。d.不要过度索引。e.定义有外键的数据列一定要建立索引。f.更新频繁的字段不适合建立索引。g.不能有效区分数据的列不适合建索引。h.尽量扩展索引不要新建索引。i.对查询中很少涉及的列重复值较多的列不要建索引。j.对于定义为text、image、bit的数据类型的列不要建索引。58. mysql锁的类型有哪些基于锁的属性分类共享锁、排它锁。基于锁的粒度分类行级锁InnoDb、表级锁InnoDb、MYISAM、页级锁BDB引擎、记录锁、间隙锁、临建锁。基于锁的状态分类意向共享锁、意向排它锁。59. 事务的基本特性和隔离级别事务基本特性ACID分别是原子性一个事务中的操作要么全部成功要么全部失败。一致性数据库总是从一个一致性的状态转换到另外一个一致性的状态。隔离性一个事务的修改在最终提交前对其他事务是不可见的。持久性一旦事务提交所做的修改就会永久保存到数据库中。隔离性有4个隔离级别分别是a.read uncommit 读未提交可能会读到其他事务未提交的数据也叫做脏读。b.read commit 读已提交两次读取结果不一致叫做不可重复读。c.repeatable read 可重复读这是mysql默认的级别每次读取结果一样但是有可能产生幻读。d.serializable 串行一般不会使用他会给每一行数据加锁会导致大量超时和锁竞争问题。60. 关心过业务系统里面的sql耗时吗统计过慢查询吗对慢查询都怎么优化过在业务系统中除了使用主键进行的查询其它都会在测试库上测试其耗时慢查询的统计主要由运维在做会定期将业务中的慢查询反馈给我没。优化的三个方面a.首先分析语句看看时否load了额外的数据可能时查询了多余的行并且抛弃掉了可能是加载了结果中不需要的列对语句进行分析及重写。b.分析语句的执行计划然后获得其使用索引的情况之后修改语句或修改索引使得语句可以尽可能的命中索引。c.如果对语句的优化已经无法进行可以考虑表中的数据量是否太大如果是的话可以进行横向或者纵向的分表。61. ACID靠什么保证A原子性由undo log日志保证它记录了需要回滚的日志信息事务回滚时撤销已经执行成功的sql。C一致性由其它三大特性保证、程序代码要保证业务上的一致性。I隔离性由MVCC多版本控制来保证。D持久性由内存redo log来保证mysql修改数据同时在内存和redo log记录这次的操作宕机的时候可以从redo log恢复。62. 什么是MVCC多版本并发控制读取数据时通过一种类似快照的方式将数据保存下来这样读锁和写锁不冲突了不同的事务session会看到自己特定版本的数据版本链。63. 简述MYISAM和InnoDB的区别MyISAM:不支持事务但是每次查询都是原子的支持表级锁即每次操作是对整个表加锁存储表的总行数一个MYISAM表有三个文件索引文件、表结构文件、数据文件采用非聚簇索引索引文件的数据域存储指向数据文件的指针。InnoDB支持ACID的事务支持事务的4种隔离级别支持行级锁及外键约束不存储总行数一个InnoDB引擎存储在一个文件空间中也可能为多个受操作系统文件大小的限制主键索引采用聚簇索引索引的数据域存储数据文件本身辅索引的数据域存储主键的值。64. 简述mysql中索引类型及对数据库的性能的影响普通索引允许被索引的数据列包含重复的值。唯一索引可以保证数据记录的唯一性。主键是一种特殊的唯一索引在一张表中只能定义一个主键索引。联合索引索引可以覆盖多个数据列如INDEXcolumnAcolumnB。全文索引通过建立倒排索引可以极大提升检索效率解决判断字段包含问题。索引可以极大的提升数据的查询速度。但是会降低插入、删除、更新表的速度因为执行这些写操作时还要操作索引文件。索引需要占用物理空间如果建立聚簇索引那需要的空间更大如果非聚簇索引很多一旦聚簇索引改变那么所有的非聚簇索引都会跟着变。65. redis中RDB和AOF机制RDBRedis DataBase在指定的时间间隔内将内存中的数据集快照写入磁盘实际操作过程是fork一个子进程现将数据集写入临时文件写入成功后再替换之前的文件用二进制压缩存储。优点整个Redis数据库将只包含一个dump.rdb方便持久化容灾性好方便备份性能最大化相对于数据集大时比AOF启动效率高。缺点数据安全性低AOFAppend Only File以日志的形式记录服务器所处理的每一个写、删除操作查询不会记录以文本的方式记录可以打开文件查看详细的过程。优点数据安全其提供了三总同步策略每秒同步、每修改同步、不同步通过append模式写文件即使中途服务宕机也不会破坏已存在内容可以通过redis-check-aof工具解决数据一致性问题AOF的rewrite模式能够定期对AOF文件进行重写达到压缩目的。缺点AOF文件比RDB文件大且恢复速度慢数据集大的时候比RDB启动效率低运行效率也没有RDB高。66. Redis过期键的删除策略惰性过期只有当访问了一个key时才会判断该key是否已过期过期则清除。定期过期每隔一定的时间会扫描一定数量的数据库的expires字典中一定数量的key并清除其中已过期的key。67. Redis线程模型单线程为什么快redis基于Reactor模式开发了网络事件处理器这个处理器又叫做文件事件处理器因为它是单线程的所以redis才叫单线程的模型它采用IO多路复用机制来同时监听多个Socket根据Socket上的事件类型来选择对应的事件处理器处理该事件。单线程快的原因a.纯内存操作。b.核心是非阻塞的IO多路复用机制。c.单线程反而避免了多线程频繁上下文切换而带来的性能问题。68. 缓存雪崩、缓存穿透、缓存击穿缓存雪崩缓存同一时间大面积的失效后面的请求都会落在数据库上造成数据库短时间内承受大量请求而崩溃掉。解决方案缓存的过期时间设置随机给缓存数据增加缓存标记缓存预热。缓存穿透缓存和数据库中都没有的数据导致所有的请求都落到数据库上造成数据库短时间内承受大量请求而崩溃掉。解决方案接口层增加校验采用布隆过滤器。缓存击穿缓存中没有但数据库中有的数据由于并发用户特别多同时读缓存没读到数据又同时去数据库取数据引起数据库压力瞬间增大。解决方案设置热点数据永远不过期。69. Redsi集群方案哨兵模式集群监控负责监控redis master 和 slave 进程是否正常工作。消息通知如果某个redis实例故障那么哨兵负责发送消息报警通知给管理员。故障转移如果master node挂掉了会自动转移到 slave node上。配置中心如果故障转移发生了通知client客户端新的master地址。哨兵用于实现redis集群的高可用本身也是分布式作为一个哨兵集群去运行互相协同工作。70. redis主从复制的核心原理a.一个从数据库在启动后会向主数据库发送SYNC命令。b.主数据库在接收到SYNC命令后会开始在后台保存快照即RDB持久化的过程并将保存快照期间接收到的命令缓存起来。在该持久化过程中会生成一个.rbd快照文件。c.在主数据库快照执行完成后Redis会将快照文件和所有缓存的命令以.rdb快照文件的形式发送给从数据库。d.从数据库收到主数据库的.rdb快照文件后载入该快照文件到本地。e.从数据库执行载入后的.rdb快照文件将数据写入内存中。【以上步骤称为复制初始化】f.在复制初始化结束后主数据库在每次收到写命令时都会将命令同步给从数据库从而保证主从数据库的数据一致。71. CAP理论BASE理论Consistency一致性更新操作成功并返回给客户端后所有节点在同一时间的数据完全一致。Availability可用性即服务一直可用而且是正常响应时间。Partition Tolerance分区容错性即分布式系统在遇到某些节点或网络分区故障时仍然能够对外提供满足一致性和可用性的服务。BASE是基本可用、软状态和最终一致性。核心思想即使无法做到强一致性但每个应用都可以根据自身业务特点采用适当的方式来使系统达到最终一致性。72. 负载均衡算法、类型a.轮询法将请求按顺序轮流的分配到后端服务器。b.随机法通过系统的随机算法根据后端服务器的列表大小值来随机选取其中的一台。c.源地址哈希法根据获取客户端的ip地址通过哈希函数计算得到一个值用该值对服务器列表的大小进行取模运算得到的结果就是客户端要访问的服务器序号。d.加权轮询法给高配置、负载低的机器配更高的权重让其处理更多的请求反之则分配较低权重降低其负载。e.加权随机法和加权轮询类似但是其是按照权重随机请求后端服务器而非顺序。f.最小连接数法根据后端服务器当前的连接情况动态的选取其中当前积压连接数最少的一台服务器来处理当前请求。类型a.DNS方式实现负载均衡。b.硬件负载均衡F5、A10。c.软件负载均衡Nginx等。73. 分布式架构下Session共享有什么方案a.采用无状态服务抛弃session。b.存入cookie有安全风险。c.服务器之前进行session同步保证每个服务器上都有全部session信息不过当服务器多时会出现延迟或失败。d.ip绑定策略同一个ip只能在指定的同一个机器访问。e.使用redis存储。74. 简述RPC、RMIRPC在本地调用远程的函数远程过程调用可以跨语言实现。RMI远程方法调用java中用于实现RPC的一种机制直接或间接实现接口 java.rmi.Remote成为存在于服务器端的远程对象供客户端访问并提供一定的服务远程对象必须实现java.rmi.server.UniCastRemoteObject类这样才能保证客户端远程访问获得远程对象时该远程对象会将自身的一个拷贝以socket的形式传给客户端。75. 分布式id生成方案a.uuid当前日期和时间时钟序列全局唯一的IEEE机器识别码优点代码简单性能好保证唯一缺点id无序存储性能差可读性差有信息安全问题如泄露mac地址。b.数据库自增序列优点实现简单成本小id数字化单调自增。缺点强依赖DB存在单点问题性能有限无法抗高并发场景。c.雪花算法生成一个64bit的整形数字第一位符号位固定为0、41位时间戳、10位workId、12位序列号位数可以有不同实现。优点性能好整个Id趋势递增灵活度高。缺点强依赖于时钟如果时钟回拨会导致重复的id生成。76. 如何实现接口的幂等性a.唯一id。每次操作都根据操作和内容生成唯一的id在执行前先判断id是否存在如果不存在则执行后续操作并保存到数据库或者redis等。b.服务端提供发送token的接口业务调用接口前先获取token然后调用业务接口请求时把token携带过去服务器判断token是否存在redis中存在表示第一次请求可以继续执行业务最后需要把redis中的token删掉。c.建去重表。将业务中有唯一标识的字段保存到去重表如果表中存在则表示已经处理过了。d.版本控制。增加版本号当版本号符合时才能更新到数据。e.状态控制。77. 简述ZAB协议ZAB协议是为分布式协调服务 Zookeeper专门设计的一种支持崩溃恢复的原子广播协议实现分布式数据一致性。ZAB协议包括两种基本的模式崩溃恢复和消息广播。消息广播集群中所有的事务请求都由Leader节点处理其他服务器为FollowerLeader将客户端的事务请求转换为事务Proposal并分发给集群中所有的Follower完成广播后等待反馈若过半数则再次广播Commit信息从而提交事务。崩溃恢复在初始化集群、Leader崩溃、Leader失去了半数机器的支持的情况下开始新一轮的Leader选举选举产生的Leader会与过半的Follower进行同步使数据一致。78. 简述ZK的命名服务、配置管理、集群管理命名服务通过指定的名字来获取资源或服务地址。配置管理把程序的配置信息保存在zk的znode节点下当你要修改配置即znode发生变化利用watcher通知给各个客户端从而更改配置。集群管理监控集群机器的状态添加或者删除机器。79. 讲一下Zookeeper watch机制客户端可以通过在znode上设置watch实现实时监听znode的变化。watch事件时一个一次性的触发器当被设置了watch的数据发生改变服务器就会将这个改变发送给设置了watch的客户端。父节点的创建、修改、删除以及子节点的创建、删除都会触发watch事件。一旦触发就会移除再次使用需要重新注册但3.6.0默认持久递归可以触发多次。该通知只会告知发生了事情不会告知具体内容以减轻服务带宽和压力。watch机制包括三个角色客户端线程、客户端的WatchManager、zookeeper服务器客户端向zookeeper服务器注册一个watch监听把这个监听信息存储到WatchManager中当zookeeper的节点发生变化时会通知客户端客户端会调用相应watch对象中的回调方法。80. ZK和Eureka的区别zk是CP设计强一致性目标是一个分布式的协调系统用于进行资源的统一管理。当节点崩溃后重新进行leader选举时服务是不可用的。eureka是AP设计高可用目标是一个服务注册发现系统专门用于微服务的服务发现注册。其中各个节点都是平等的几个节点挂掉并不影响整体剩余还可以提供注册和查询服务。81. SpringCloud和Dubbo的区别底层协议springcloud基于http协议dubbo基于tcp协议dubbo的性能相对较好。注册中心springcloud使用eurekadubbo推荐使用zookeeper。模型定义springcloud将一个应用定义为一个服务dubbo则是将一个接口定义为一个服务。springcloud是一个生态而dubbo是springcloud生态中关于服务调用的一种解决方案服务治理。82. 什么是Hystrix分布式容错框架阻止故障的连锁反应实现熔断快速失败实现优雅降级提供实时的监控和告警。a.通过HystrixCommand将所有的外部系统包装起来整个包装对象时单独运行在一个线程之中。b.超时请求应该超过你定义的阈值。c.为每个依赖关系维护一个小的线程池或信号量如果它变满了那么依赖关系的请求将立刻被拒绝而不是排队等待。d.统计成功、失败、超时和线程拒绝。e.打开断路器可以在一段时间内停止对特定的服务的所有请求如果服务的错误百分比通过阈值手动或自动的关闭断路器。f.当请求被拒绝、连接超时或者断路器打开执行fallback逻辑。g.近乎实时监控指标和配置变化。83. springcloud核心组件及其作用Eureka服务注册发现注册每个服务都向Eurka登记自己的服务信息eureka将各个服务维护在一个服务清单中双层Map第一层key服务名第二层key实例名value服务地址加端口同时对服务维持心跳剔除不可用的。发现eureka注册的服务之前调用通过服务名向注册中心咨询并获取所有的服务实例清单然后实现服务的请求访问。Ribbon负载均衡基于http发起请求通过调用服务名的地址来实现。Feign基于feign的动态代理机制根据注解和选择的机器拼接请求url地址发起请求。Hystrix发起请求时通过hystrix的线程池来走的不同服务走不同的线程池实现了不同服务调用的隔离通过统计接口超时次数返回默认值实现服务熔断和降级。Zuul如果前端、移动端要调用后端系统统一从Zuul网管进入由Zuul网管转发请求给对应的服务通过与Eureka进行整合将自身注册为Eureka下的应用从Eureka下获取所有服务的实例来进行服务的路由其还提供的有一套过滤机制。84. Dubbo的整体架构五个角色注册中心registry服务注册与发现。服务提供者provider暴露服务。服务消费者consumer调用远程服务。监控中心monitor统计服务的调用次数和调用时间。容器container服务允许容器。调用流程a.container容器负责启动、加载、运行provider。b.provider在启动时向registry中心注册自己提供的服务。c.consumer在启动时向registry中心订阅自己所需要的服务。d.registry返回服务提供者列表给consumer如果有变更registry将基于长链接推送变更给consumer。e.consumer调用provider服务基于负载均衡算法进行调用f.consumer调用provider的统计基于短链接定时每分钟一次统计到monitor。85. 简述RabbitMQ的架构设计Brokerrabbitmq的服务节点。Queue队列是rabbitmq的内部对象用于存储信息。Exchange交换器。生产者将消息发送到Exchange由交换器将消息路由到一个或多个队列中如果路由不到或返回给生产者或直接丢弃或做其他处理。RoutingKey路由Key。生产者将消息发送给交换器时一般会指定一个rountingkey用来指定这个消息的路由规则。这个key需要与交换器类型和绑定键BindingKey联合使用才能生效。交换器和绑定器是多对多的关系。信道建立在Connection之上的虚拟连接。当应用程序与Rabbit Broker建立TCP连接时客户端紧接着可以创建一个AMQP信道每个信道都会被指派一个唯一的id。RabbitMQ处理的每条AMQP指令都是通过信道完成。86. RabbitMQ如何确保消息发送和消息接受发送方确认机制信道需要设置为confirm模式在信道上发布的消息都会分配一个唯一的id一旦消息被投递到queue信道会发送一个确认给生产者包含消息唯一id如果rabbitmq发生内部错误从而导致消息丢失会发送一条nack未确认给生产者。所有被发送的消息都将被ack或nack一次发送方确认模式是异步的生产者在等待确认的时候可以继续发送当确认消息到达生产者时生产者回调方法会被触发。接收方确认机制消费者在声明队列时可以指定noAck参数当该参数为false时RabbitMQ会等待消费者显示发回ack信号后才从内存中移去消息否则消息被消费后会立即删除。RabbitMQ不会为未接收的消息设置超时时间它判断此消息是否需要重新投递给消费者的唯一依据是该消费者连接是否断开。如果消费者返回接收之前断开了连接RabbitMQ会重新分发给下一个订阅的消费者可能存在重复消费的隐患需要去重。87. RabbitMQ事务消息通过将信道Channel设置为事务模式所有发送到该通道的消息都将在提交事务之前被缓存并且在提交事务后才会被投递到交换机中。如果事务提交失败可以进行事务回滚使消息不会被发送。a.channel.txSelect通知服务器开启事务模式服务端会返回Tx.Select-Ok;b.发布消息到交换机channel.basicPublish(…);c.提交事务channel.txCommit();d.Broker 回复 Tx.Commit - Ok 确认事务提交;e.Broker回复超时或者出现异常回滚事务channel.txRollback()。​
返回列表