- 请说说多线程?
线程是程序执行的最小单元,一个过程能够领有多个线程;各个线程之间共享程序的内存空间和零碎调配的资源,然而各个线程领有本人的栈空间;多线程的长处能够缩小程序的响应工夫,进步 CPU 利用率。
- 怎么保障线程平安?
线程平安问题是指在多线程背景下,线程没有依照咱们的预期执行,导致操作共享变量出现异常。在 Java 中有三种形式:原子类、volatile 关键字、锁。
- 说说你对反射的了解?
反射就是在程序运行期间动静的获取对象的属性和办法的性能叫做反射。它可能在程序运行期间,对于任意一个类,都能晓得它的所有的办法和属性,对于任意一个对象,都能晓得他的属性和办法。获取 Class 对象的三种形式:getClass();xx.class;Class.forName(“xxx”); 反射的长处:运行期间可能动静的获取类,进步代码的灵活性。毛病:性能比间接的 Java 代码要慢很多。利用场景:spring 的 xml 配置模式,以及动静代理模式都用到了反射。
- ArrayList 和 LinkedList 的区别?
ArrayList 底层是数组实现的,数组是一组间断的内存单元,读取快(应用索引),插入删除慢(须要从新计算大小或是更新索引)LinkedList 底层基于双向链表,读取慢,插入删除快。
- 你晓得哪些线程平安的汇合?
java.util 包中的汇合类大部分都是非线程平安的,例如:ArrayList/LinkedList/HashMap 等等,但也有少部分是线程平安的,像是 Vector 和 Hashtable,它们属于很古老的 API 了,是基于 Synchronized 实现的,性能很差,在理论的开发中不罕用。个别能够应用 Collections 工具类中的 synchronizedXxx() 办法将非线程平安的汇合包装成线程平安的类。在 java5 之后能够应用 concurrent 包提供的大量的反对并发拜访的汇合类,例如 ConcurrentHashMap/copyOnWriteArrayList 等。
- String、StringBuffer、StringBuilder 有什么区别?
StringBuilder 和 StringBuffer 十分相似,均代表可变的字符序列,而且办法也一样。String 是不可变字符序列,效率低,然而复用率高;StringBuffer 是可变字符序列、效率较高(增删)、线程平安;StringBuilder 是可变字符序列、效率最高、线程不平安。
- 说说 HashMap 的底层原理?
HashMap 的底层是数组 + 链表 + 红黑树实现的。汇合 put 时,通过计算 key 键的哈希值来放入元素。若有 key 值雷同的哈希值时,会通过链表进行寄存,链表长度达到 8 时会开拓红黑树进行寄存,以此进步查问效率。
- 说说你理解的 JVM 内存模型?
JVM 由三局部组成:类加载子系统、执行引擎、运行时数据区。类加载子系统:能够依据指定的全限定名来载入类或接口;执行引擎:负责执行哪些蕴含在被载入类的办法中的指令;运行时数据区:分为办法区、堆、虚拟机栈、本地办法栈、程序计数器,当程序运行时,JVM 须要内存来存储许多内容,例如:字节码、对象、参数、返回值、局部变量、运行时的两头后果等,把这些货色都存储到运行时数据区中,以便于管理。
- 说说 JVM 的垃圾回收机制?
垃圾回收通常有三件事件要做。第一将决定哪些对象要回收,jvm 决定了将未被援用的对象占用空间回收,通常用援用计数法或者可达性分析法,后者时 jvm 支流应用办法;第二是什么时候回收 jvm,通常在内存不够用时,或定期回收;第三用什么形式回收,有分代回收,分区域回收法,收集器有年老代收集器、老年代收集、混合收集、整堆收集。
- 说说 JVM 的垃圾回收算法?
援用计数法:每次赋值时均要保护援用计数器自身也有肯定的耗费,较难解决循环援用,个别不采纳这种形式;复制算法:将内存分为两块,每次只应用其中一块,当这块内存用完,就将还活着的队形复制到另一块下面,效率高且没有碎片,然而须要双倍的空间,年老代中应用复制算法;标记革除:先标记要革除的对象,而后对立回收这些对象,不须要额定的空间,但还是须要两次扫描,耗时重大并且会产生内存碎片;标记整顿:标记存活对象,而后将标记的存货对象按内存地址顺次排序,革除边界外未标记的对象,没有内存碎片,然而须要挪动对象。老年代个别有标记 - 革除和标记 - 整顿的混合实现。
- 说说类加载机制?
类加载的过程中首先判断这个是否被加载过,如果没有被加载过,那么调用类加载器进行加载,判断这个类是否符合规范,如果不合乎就抛出异样,加载胜利就会成 class 对象。接下来是链接过程,分为三步:验证、筹备、解析。验证:确保文件符合规范,不会危害虚拟机本身的平安,对文件格式,字节码,元数据,符号援用进行验证;筹备:为类变量调配初始空间以及默认初始值,即零值,这里不会为实例变量调配,类变量调配在办法区中,实例变量追随对象调配在堆中,final 润饰的在编译期间就调配了,在筹备阶段会显示的初始化;解析:将常量池内的符号援用转为间接援用的过程。链接过程实现之后开始初始化的过程:初始化阶段就是执行类构造方法的过程,此办法不须要定义,一个类只会被加载一次,虚拟机必须保障在多线程条件下类的构造方法是被加锁的。
- 说一下抽象类和接口的区别?
抽象类多用于在同类事物中有无奈具体形容的办法的场景,而接口多用于不同类之间,定义不同类之间的通信规定;接口只有定义,而抽象类能够有定义和实现;接口须要实现,抽象类只能被继承,一个类能够实现多个接口,但一个类只能继承一个抽象类;抽象类偏向于充当公共类的角色,当性能须要累计时,用抽象类;接口被使用于实现比拟罕用的性能,性能不须要累计时,用接口。
- 请说说 == 与 equals() 的区别?
== 比拟根本数据类型时,比拟的时两个数值是否相等;比拟援用类型时,比拟的是对象的内存地址是否相等。equals() 没有重写时,Object 默认以 == 来实现,即比拟两个对象内存地址是否相等;重写当前对象的内容进行比拟。
- 说说 synchronize 的用法及原理?
用法:1. 静态方法上,则锁的是以后类的 Class 对象;2. 作用在一般办法上,则锁的是以后的实例(this);3. 作用在代码块上,则须要在关键字前面的小括号里,显示指定一个对象作为锁对象。可能保障同一个时刻只有一个线程执行该段代码,保障线程平安,在执行实现或者出现异常时主动开释锁。原理:底层是采纳 Java 对象头来存储锁信息的,并且还反对锁降级。在 jvm 里的实现都是基于进入和退出 Monitor 对象来实现办法同步和代码块同步。
- 说说你对 AQS 的了解?
AQS 队列同步器,用来构建锁的根底框架,Lock 实现类都是基于 AQS 实现的。它的原理就是保护一个共享资源,而后利用队列让线程队列获取资源的一个过程。外部实现的要害是队列和 state 状态,。它有两种线程模式:独占和共享模式。
- java 哪些地方应用了 CAS?
CAS 的全程是 CompareAndSwap 直译为比拟和替换。它是广泛处理器都反对的一条指令,这条指令通过判断以后内存值 V,旧的预期值 A,行将更新的值 B 是否相等来比照并设置新值,从而实现变量的原子性。CAS 比拟典型的应用场景有原子类、AQS、并发容器。
- 说说 static 修饰符的用法?
static 润饰变量:属于动态变量也叫类变量,置属于类对象而不是实例,能够通过类名拜访,它个别会在类加载过程中被初始化,生命周期贯通整个程序,存储在办法区中;static 润饰办法:即静态方法,一个类中的静态方法不能拜访该类的实例变量,只能拜访动态变量,同时还存在一个动态初始化块,他在类加载过程中被调用用于对该类中的动态变量进行操作;static 润饰类:即动态外部类,他只能以内部类的模式存在,能够通过外部类的类名调用,它是也只能拜访到内部的动态成员。
- 说说线程的状态?
线程的状态有 6 种。1. 初始:线程被创立然而还没有调用 start() 办法;2. 运行(就绪和运行):线程正在执行,但也可能在期待操作系统的调度;3. 阻塞:若一个运行中的线程存在同步操作,此时锁被其余线程占用,该线程就会进入阻塞态期待获取锁;4. 限期期待:正在运行的线程执行了 Thread.sleep() 办法或者设置了 timeout 的 wait() 办法,join 办法等进入肯定工夫的期待,零碎主动唤醒;5. 不限期期待:正在运行的线程执行了未设置 timeout 的 wait 办法或 join 办法进入期待,只有通过其余线程应用 interrupt() 或 notify 办法对其进行唤醒;6. 死亡态:线程胜利执行结束或执行中抛出异常中断了线程会进入死亡态。
- 说说你对 ThreadLocal 的了解?
ThreadLocal 即线程变量,它将须要并发拜访的资源复制多份,让每个线程领有一份资源,因为每个线程都领有本人的资源正本,从而也就没有必要对该变量进行同步了。实现原理:每个 Thread 对象中都有一个 ThreadLocal 类的外部类 ThreadLocalMap 对象,他是一个键值模式的容器,以 ThreadLocal 对象的 get 和 set 办法来存取共享变量值,一个 ThreadLocal 用完后必须 remove,否则会造成内存泄露。
- synchronized 和 Lock 有什么区别?
1.synchronized 比 Lock 锁接口呈现要早;2.synchronized 即能够润饰静态方法,也能够润饰实例办法以及代码块;3.synchronized 的实现形式是基于 JVM 的,外人不能更改,而 lock 锁接口是内部 API;4.synchronized 反对的性能少于 lock 锁接口,lock 锁接口在反对 synchronized 原有性能的根底上,还反对超时机制和响应中断等性能;5.synchronized 底层采纳 java 对象头来存储锁信息,lock 实现类是基于 AQS 实现的,晚期 synchronized 的性能很差,只有”无锁“和”有锁“两种状态,但前期 synchronized 引入了锁降级机制,有了很大改善,锁当初有四种状态:无锁、偏差锁、轻量级锁、重量级锁,缩小了获取锁和开释锁带来的性能耗费。
- 说说 volatile 的用法及原理?
volatile 次要用于润饰多线程中的共享变量,它能够保障变量的可见性和有序性,不能保障原子性。可见性是指在多线程环境中若某个线程批改了该变量,那么其余线程就能察觉到变量的批改。可见性次要是通过在内存模型中批改了某值则将它同步回主内存,在读取前从主内存刷新该变量值来实现的。有序性是指在某个线程中对该变量的操作程序是通明的,不会扭转的。在 java 中因为寄存器和内存处理速度存在微小差别所以 java 为了晋升运行速度会将编译好的代码进行肯定水平的重排,但不影响其在独立线程环境下的运行后果,然而在多线程环境中有可能出错。volatile 能够防止这种指令重排实现其在多线程的程序统一的成果。
- 说一下 final 关键字?
final 被用来润饰类和类的成分。final 属性:变量援用不可变,但对象外部内容可变,被 final 润饰的变量必须被初始化;final 办法:该办法不能被重写,但子类能够应用该办法;final 参数:参数在办法外部不容许被批改;final 类:该类不能被继承,所有办法不能被重写,但未被申明为 final 的成员变量能够扭转。
- 请你说说重载和从新的区别,构造方法能不能重写?
重载产生在同一个类中,要求办法名必须雷同,参数列表不同,重载的产生与办法的返回值和拜访修饰符无关,最终是生成了两个办法。重写是产生在父子类中的,子类重写办法的名称和参数列表必须和父类雷同,子类的返回类型或抛出的异样类型必须是父类的返回值或异样类型及其子类型。子类重写办法的拜访修饰符必须大于父类,若父类办法的修饰符为 private 则子类不能重写该办法。
- 说说你对 Java 汇合的理解?
java 中的汇合类次要都有 Collection 和 Map 这两个接口派生而出,其中 Collection 又派生出 List、Set、Queue。所有的汇合类都是 List、set、queue、map 这四个接口的实现类。其中 list 代表有序的、可反复的数据汇合;set 代表无序的、不可反复的数据汇合;queue 代表先进先出的队列;map 是又映射关系的汇合。最罕用的实现类有:ArrayList、LinkedList、HashMap、TreeMap、HashSet、TreeSet、ArrayQueue。
- 请你说说 IO 多路复用?
IO 多路复用指的是单个线程同时实现对多个 IO 事件的监听解决。linux 提供了 select、poll、epoll 三种多路复用形式。select 调用:查问有多少个文件描述符须要进行 IO 操作,特点:轮询次数多,内存开销大,反对文件描述符的个数无限;poll 调用:和 select 简直差不多,然而它的底层数据结构为链表,所以反对文件描述符的个数无下限;epoll:更加高效的调用形式,底层的数据结构为红黑树加链表,防止大内存调配和轮询。
- 请你讲一下 java8 的新个性?
1.Lambda 表达式:可将性能视为办法参数,或者将代码视为数据,应用 Lambda 表达式能够简洁地示意单办法接口的实例;2. 办法援用:提供了十分有用的语法,可间接援用已有 Java 类或对象的办法或结构器。与 lambda 联结应用,办法援用能够使语言的结构构造更紧凑简洁,缩小冗余代码;3. 对接口进行了改良:容许在接口中定义默认办法,默认办法必须应用 default 润饰;4.Stream API:新增加的 Stream API 反对对元素流进行函数式操作;5.Date Time API:增强对日期工夫的解决。6.Optional 类:用来解决空指针异样。
- 请你说说泛型、泛型擦除?
泛型:java 在 jdk1.5 时引入了泛型,在没有泛型之前,每次从汇合中读取的对象都必须进行类型转换,如果在插入对象时,类型出错,那么在运行时转换解决的阶段就会出错,在提出泛型之后就能够明确的指定汇合承受哪些对象类型,编译器就能通晓并且主动为插入的代码进行泛化,在编译阶段告知是否插入类型谬误的对象,程序会变得更加平安清晰。泛型擦除:java 泛型是伪泛型,因为 java 代码在编译阶段,所有的泛型信息会被擦除,java 的泛型基本上都是在编译器这个档次上实现的,在生成的字节码文件中不蕴含泛型信息的,应用泛型的时候加上的类型,在编译阶段会被擦除掉,这个过程成为泛型擦除。
- 说说你理解的线程通信形式?
在 java 中提供了两种多线程通信形式别离是利用 monitor 和 condition 两种。具体应用那种通信形式与线程同步形式无关。对于 synchronized 来说,应用的是 monitor 的同步形式。罕用的办法有 wait(),notify(),notifyAll()。对于 lock 锁接口来说,应用的是 condition,依赖于 lock 锁的创立而创立,常应用的办法有 await(),signal(),signalAll()。
- 说说 JUC?
JUC 是 java.util.concurrent 的缩写,这个包中蕴含了反对并发操作的各种工具。1. 原子类:遵循比拟和替换准则。能够用于解决单个变量的线程平安问题;2. 锁:与 synchronized 相似,在蕴含 synchronized 所有性能的根底上,还反对超时机制,响应中断机制,次要用于解决多个变量的线程平安问题;3. 线程池:能够更不便的治理线程,同时防止反复开线程和杀线程带来的耗费,效率高;4. 并发容器:例如 ConcurrentHashMap,反对多线程操作的并发汇合,效率更快。
- 说说 HashMap 和 Hashtable 的区别?
Hashtable 在实现 Map 接口时保障了线程安全性,而 HashMap 则时非线程平安的,所以 Hashtable 的性能不如 HashMap, 因为为了保障线程它就义了一些性能。Hashtable 不容许存入 null,无论是以 null 作为 key 或 value,都会引发异样但 HashMap 是容许的。Hashtable 是很古老的 api,性能不好,不举荐应用,要在多线程下应用 ConcurrentHashMap,它岂但保障了线程平安,也通过升高锁的粒度进步了并发拜访时的性能。
- 说说 java 的四种援用形式?
1. 强援用:以 new 关键字创立的援用都是强援用,被强援用的对象永远都不会被回收;2. 软援用:以 SoftRerference 援用对象,被软援用的对象只有在内存不足时会被垃圾回收;3. 弱援用:以 WeakReference 援用对象,被弱援用的对象肯定会被回收,它只能存活到下一次垃圾回收;4. 虚援用:以 PhantomReference 援用对象,一个对象被援用后不会有任何影响,也无奈通过该援用来获取该对象,常识其再被垃圾回收时会收到一个零碎告诉。
- 说说你对 ArrayList 的了解?
arrayList 在 jdk1.7 的时候,创立容器的时候会在底层创立一个长度为 10 的 object 数组,在 jdk1.8 的时候,在创立容器的时候底层并不会立即创立,只有在第一次调用 add 办法的时候才会创立一个长度为 10 的数组,默认状况下,扩容为原来容量的 1.5 倍,同时将原有数组中的值复制到新的数组中,并且 arraylist 属于有序的,可反复的汇合,提供了 iterator 办法,加强了迭代能力。
- 说说 BIO、NIO、AIO?
unix 提供了五种 IO 模型:阻塞 IO、非阻塞 IO、IO 多路复用、信号驱动 IO、异步 IO。BIO 对应的时阻塞 IO,一次只能操作一个 IO;NIO 是 IO 多路复用,一个线程能够同时解决多个 IO 申请,IO 多路复用模型提供 select、poll、epoll 调用;AIO:也是基于 epoll,特点是无效的申请才启动线程,现有操作系统实现再告诉服务端。
- 说说垃圾收集器?
Serial(新生代)、Serial Old(老年代):实用于单核小 CPU,单核工作,回收时会暂停其余工作 stop the world;PawNew(新生代)、CMS(老年代):实用于多核 CPU,谋求短暂工夫,多核工作,应用标记革除算法,最短的暂停工夫;Parallel Scavenge(新生代 - 标记复制算法)、Parallel Old(老年代 - 标记整顿算法):1.7,1.8 默认的组合,实用于多核 CPU,谋求最大吞吐量;G1 jdk1.9 默认,应用于大内存多核 CPU 服务器,它不按整个新生代或老年代去回收,而是开拓了面向部分收集,实现了较小的收集暂停工夫和高吞吐量。
- 说说 java 的特点和长处,为什么要抉择 java?
1. 排汇了 c ++ 的长处,摒弃了 c ++ 多继承和指针的简单应用,不须要对内存进行开释,具备垃圾回收机制;2. 面向对象,易于开发和了解;3. 跨平台,因为 jvm,同一个代码能够再不同的平台机器上运行,.java 文件通过编译成.class 字节码文件再由 jvm 转成机器能辨认的机器码;4. 内含大量的库,简化编写工作;5. 应用于开发 web.
- 介绍一下包装类的主动拆装箱与主动装箱?
主动装箱、主动拆箱时 JDK1.5 提供的性能;主动装箱:把一个根本类型的数据间接赋值给对应的包装类型;主动拆箱是指把一个包装类型的对象间接赋值给对应的根本类型;通过主动装箱、主动拆箱性能简化根本类型变量和包装类对象之间的转换过程。
- 说说 wait() 和 sleep() 的区别?
sleep 办法是以后线程的休眠,让出 cpu,然而不开释锁,它是 Thread 的静态方法,wait 是以后线程期待,开释锁,是 Object 的办法;sleep 没有开释锁,wait 开释锁,两者都可暂停线程的执行,wait 用于线程间的通信,sleep 用于暂停线程。wait 期待过程不占用 CPU,sleep 依然占用。wait 调用后,须要别的线程调用同一个对象的 notify 办法。
- 说说你对线程池的了解?
线程池能够无效的治理线程:1. 它能够治理线程的数量,能够防止无节制的创立线程,导致超出零碎负荷直至解体;2. 它能够让线程复用,能够大大地缩小创立和销毁线程所带来地开销。线程池须要依赖一些参数来管制工作地执行流程,其中最重要地参数有:corePoolSize 外围线程池数、workQueue 期待队列、maxinumPoolSize 最大线程池数、handler 回绝策略、keepAliveTime 闲暇线程存活工夫。当咱们想线程池提交一个工作之后,线程池依照如下步骤解决这个工作:1. 判断线程数是否达到 corePoolSize,若没有则新建线程执行该工作,否则进入下一步;2. 判断期待队列是否已慢,若没有则将工作放入期待队列,否则进入下一步;3. 判断线程数是否达到 maxinumPoolSize,如果没有则新建线程工作,否则进入下一步;4. 采纳初始化线程池时指定地回绝策略,拒绝执行该工作;5. 新的线程解决完当前任务后,不会立刻敞开,而是持续解决期待队列中地工作。如果线程地闲暇工夫达到了 keepAliceTime,则线程池会销毁一部分线程,将线程地数量膨胀至 corePoolSize。第二步中地队列能够有界也能够无界,若指定无界队列,则线程池永远无奈进入第三步,相当于废除了 MaxinumPoolSizecabs 参数。这种做法是非常危险的,如果工作在队列中产生大量的沉积,就很容易造成内存泄露。JDK 为咱们提供了一个名为 Executors 的线程池的创立工具,该工具创立进去的就是带有无界队列的线程池,所以个别在工作中咱们不倡议应用这个类来创立线程池。
- 说说 JVM 的双亲委派模型?
双亲委派模型的工作过程是,如果一个类加载器收到了类加载的申请,它首先不会本人去尝试加载这个类,而是把这个申请委派给父类加载器去实现,每一档次的类加载器都是如此,因而所有的加载申请最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈本人无奈实现这个加载申请时,子加载器才会尝试本人去实现加载。双亲委派模型最大的长处是能够防止类的笼罩。
- 说说 java 根本数据类型和援用类型?
8 种根本数据类型的变量的值寄存在栈内存,有 char(16)、byte(8)、short(16)、int(32)、long(64)、float(32)、double(64)、boolean。援用类型的变量寄存援用地址,堆内存才是真正的值。类,接口,数组,string 等为援用类型。
- 说说 java 的异样解决机制
1. 异样解决机制让程序具备容错性和健壮性,程序运行呈现情况时,零碎会生成一个 Exception 对象来告诉程序;2. 解决异样的语句由 try、catch、finally 三局部组成。try 块用于包裹业务代码,catch 块用于捕捉并解决某个类型的异样,finally 块则用于回收资源;3. 如果业务代码产生异样,零碎创立一个异样对象,并将其提交给 JVM,由 JVM 寻找能够解决这个异样的 catch 块,并将异样对象交给这个 catch 块解决。如果 JVM 没有找到,运行环境终止,java 程序退出;4.java 也容许程序被动抛出异样,当业务代码中,判断某项谬误的条件成立时,能够应用 throw 关键字向外抛出异样。
- 说说你对面向对象的了解?
1. 面向对象的三大基本特征:封装、继承、多态;2. 封装:将对象的状态信息暗藏在对象外部,不容许内部程序间接拜访对象外部信息,让内部程序通过该类提供的办法来实现对外部信息的操作和拜访,进步了代码的可维护性;3. 继承:实现代码复用的重要伎俩,通过 extends 实现类的继承,实现继承的类被称为子类,被继承的类称为父类;4. 多态的实现离不开继承,在设计程序时,咱们能够将参数的类型定义为父类型,在调用程序时依据理论状况,传入该父类型的某个子类型的实例,这样就实现了多态。
- 请介绍一下拜访修饰符?
private 只能在以后类的外部被拜访;default 能够被雷同包下的其它类拜访;protected 能够被同一个包下的拜访;public 无论拜访类和被拜访类在不在一个包下,有没有父子关系,这类成员都根本被拜访到。
- 说说 java 中罕用的锁及原理?
通过 synchronized 关键字和 Lock 接口两种形式实现加锁。1.synchronized 关键字通过 monitor(同步监视器)来实现锁的获取和开释,每一个 monitor 相当于一个有序队列,底层通过 java 对象头的形式存储锁的信息;2. 通过实现 Lock 接口,创立一个 local,显式指定锁对象,每一个锁对象是一个 condition,通过 condition 来实现线程同步,能够有多个,每个 condition 就是一个有序队列,相比 synchronized 的 Lock 更加灵便,Lock 底层是通过 AQS 形象同步队列实现有序队列,同时还定义乐同步状态 state 来记录锁的信息。
- 说说 List 与 Set 的区别?
List 和 Set 都是 Collection 接口的子接口,它们的次要区别在于元素的有序性和重复性:List 代表有序的元素能够反复的汇合,汇合中每个元素都有对应的顺序索引,它默认按元素的增加程序设置元素的索引,并且能够通过索引来拜访指定地位的汇合元素,另外,List 容许应用反复元素;Set 代表无序的元素不可反复的汇合,它通常不能记住元素的增加程序。
- 请讲一下 java nio?
nio 补救了原来同步阻塞 io 的有余,它在规范的 java 代码中提供了高速的、面向块的 io。nio 有三个外围组件,别离是 Buffer、Channel、Selector。Buffer:缓冲区,读写数据都要进过缓冲区,而不是通过流;Channel:通道,全双工双向通道,用来读取和写入数据的;Selector:多路复用器,一直的轮询注册在 Selector 上的 Channel,如果有新的 TCP 接入,就会被轮询进去,Channel 变成就绪状态,SelectionKey 获取 Channel 的汇合,进行后续 io 操作。JDK 应用 epoll(),没有了最大连贯句柄 1024/2048 的限度,一个线程负责 Selector 的轮询,就能接入成千上万的客户端。
- 说说你对 MVC 的了解?
MVC 是一种设计模式,在这种模式下软件被分为了三层,model 模型层、view 试图层、controller 管制层,模型层次要是定义实体对象等数据,视图层次要是用户界面等,管制层次要是具体的业务逻辑相干负责申请的散发、把模型数据及时的反映在页面上,三者之间各司其职,升高了业务之间的耦合度。spring MVC 框架就是 MVC 设计模式的最好实现。
- 说说你对 AOP 的了解?
AOP 是面向切面编程,它是一种编程思维,它是通过一种预编译形式和运行期间动静代理的形式实现不批改源码的状况下给程序动静增加性能的一种技术,能够升高代码的耦合度,便于管理,进步代码的可重用性。AOP 的实现形式有两种:JDK 动静代理,能够在运行时创立接口的代理实例。CGLib 动静代理:能够在运行期间创立子类的动静实例。AOP 的利用场景有:事务,日志治理等。
- 说说你对 IOC 的了解?
管制反转。管制:对象的创立的管制权限;反转:将对象的管制权限交给 spring。之前咱们创建对象时用 new,当初间接从 spring 容器中取,保护对象之间的依赖关系,升高对象之间的耦合度。实现形式为依赖注入,有三种注入形式:结构器、setter、接口注入。
- 说说 spring boot 罕用的注解?
@SpringBootApplication 是 springBoot 的外围注解,用于开启主动配置,精确的说是通过注解内的 @EnableAutoConfiguration 注解实现的主动配置;@EnableAutoConfiguration 主动配置注解,在启动 Spring 利用上下文时进行主动配置,主动配置通常时基于我的项目 classpath 中引入的类和已定义的 bean 来实现的;@Configuration 配置类注解,依据一些特定条件来管制 bean 的实例化的行为;@ComponentScan:地位在 springBoot 的启动类上,spring 包扫描。
- 说说 Bean 的作用域,以及默认作用域?
Bean 有五种不同的作用域 singleton、prototype、session、request、golbal session,默认状况下,Bean 在 spring 容器中是单例的,然而咱们能够通过 @Scope 注解来批改 Bean 的作用域。1.singleton:在 spring 容器中仅存在一个实例,即 bean 以单例模式存在;2.prototype:每次调用 getBean() 的时候,会 new 一个新的实例并返回;3.Session:同一个 Http 下的 session 共享一个 Bean,不同 HTTP 下不同的 session 应用不同的 Bean;4.request:每一次 HTTP 申请都会创立一个新的 Bean;5.globalSession:同一个全局 Session 会共享一个 Bean。
- 说说 Bean 的生命周期?
创立、初始化、调用、销毁;bean 的创立形式有四种,结构器、动态工厂、实例工厂、setter 注入的形式。spring 在调用 bean 的时候因为作用域的不同,不同的 Bean 初始化和创立的工夫也不同。在作用域为 singleton 的时候,bean 是随着容器一起被创立好并且实例化的,在作用域为 prototype 的时候,bean 是随着它被调用的时候才创立和实例化实现。而后程序就能够应用 bean 了,当程序实现销毁的时候,bean 也被销毁。
- 简略介绍一下 spring?
spring 是一个轻量级企业应用开发框架,它有两大外围性能,别离是 ioc 和 aop,ioc 管制反转是将创建对象的权限交给 spring 容器来进行治理,能够很好的起到解耦的作用,aop 是一种编程思维,底层应用的是动静代理,能够在程序原有的性能上进行加强,罕用的中央有日志记录,权限验证等。
- 说说你对 spring boot 的了解,以及它和 spring 的区别?
从实质上来说,springboot 就是 spring,它帮你实现了一些 springbean 配置;springboot 应用习惯优于配置的理念让你的我的项目疾速运行起来;但 springboot 自身不提供 spring 的外围性能,而是作为 spring 的脚手架框架疾速达到构建我的项目的目标;springboot 的长处,能够疾速构建我的项目,能够对支流开发框架的无配置集成,我的项目可独立运行,无需内部依赖 servlet 容器,提供运行时的利用监控,能够极大的进步开发和部署效率,能够与云计算人造集成;外围性能:1. 主动配置:针对很多 spring 应用程序常见的利用性能,springboot 能主动提供相干配置。2. 起步依赖:springboot 通过起步依赖为我的项目的依赖治理提供帮忙。起步依赖其实就是非凡的 maven 依赖和 gradle 依赖,利用了传递依赖解析,把罕用库聚合在一起,组成了几个为特定性能而定制的依赖。3. 端点监控 Lspringboot 能够对正在运行的我的项目提供监控。
- 说说 springboot 的主动拆卸?
springboot 主动拆卸时,须要引入相应的 starter,启动 springboot 后会主动配置相应的依赖和配置相应的初始化参数,以最便捷,最简略的形式实现第三方软件的集成。具体的配置过程是:springboot 通过 @EnableAutoConfiguration 开启主动配置性能,加载 spring.factories 中注册的 AutoConfiguration 类,当某个 AutoConfiguration 类满足指定的失效条件时,实例化该 AutoConfiguration 中定义的 Bean,并注入到 spring 容器中,实现依赖框架的主动配置。
- 说说 springboot 的启动流程?
当 springboot 我的项目实现创立后会默认生成一个 Application 的入口类,该类中的 main 办法能够启动 springboot 我的项目,在 main 办法中,通过 springApplication 的静态方法,即 run 办法进行 springApplication 的实例化操作,而后针对该实例化对象调用另一个 run 办法去实现整个我的项目的初始化和启动;SpringApplication 的 run 办法的中重要操作:获取监听器的参数配置,打印 Banner 信息,创立并初始化容器,监听器发送告诉。
- 介绍一个 spring MVC 的执行流程?
1. 用户向服务器发送申请,申请被 spring 的前端管制 Servlet DispatcherServlet 捕捉;2.DispatcherServlet 对申请 URL 进行解析,失去申请资源标识符 URI,而后依据该 URI 调用 HandlerMapping 取得该 Handler 配置的所有相干的对象,最初以 HandlerExecutionChain 对象的模式返回;3.DispatcherServlet 依据取得的 Handler,抉择一个适合的 HandlerAdapter,提取 request 中的模型数据,填充 handler 入参,开始执行 handler(controller),Handler 执行实现后,向 DispatcherServlet 返回一个 ModelAndVuew 对象;4.DispatcherServlet 依据返回的 ModelAndView 抉择一个适合的 ViewResolver;5. 通过 ViewResolver 联合 Model 和 View 来渲染视图,DispatcherServlet 将渲染后果返回给客户端。
- 说说 spring 的事务管理?
spring 为事务提供了统一的模板,反对两种事务编程模型:1. 编程式事务:spring 提供了 TransactionTemplate 模板,利用模板咱们能够通过编程的形式实现事务管理,而无需关怀资源获取,服务,开释事务以及异样解决,编程式事务用法麻烦,然而能够事务管理的范畴管制的更加精准;2. 使命式事务:申明式事务用法非常不便,咱们只需在类或办法上加上 @Transactional 注解便能够申明事务性,它是 spring 事务管理的亮点,在 IOC 配置中,指定事务的边界和事务属性,spring 会主动在特定的事务边界上利用事务个性。
- 说说 @Autowired 和 @Resource 注解的区别?
@Autowired 是 spring 提供的注解,而 @Resource 是 JDK 提供的注解。@Autowired 默认按类型拆卸,默认状况下必须要求依赖对象存在,如果要容许 null 值,能够设置它的 required 属性为 false。如果想应用名称拆卸能够联合 @Qualifier 注解进行应用。@Resource 默认依照名称进行拆卸,名称能够通过 name 属性进行指定,如果没有指定 name 属性,当注解写在字段上时,默认取字段名进行名称查找。
- mybatis 中 #和 $ 有什么区别?
在 MyBatis 中 $ 和 #的两种展位符,应用 $ 设置参数时,mybatis 会创立一般的 sql 语句,执行 sql 时,间接将参数拼接在 sql 中,可能会产生 sql 注入攻打,但在某些场景中,比方须要动静指定 sql 语句中的列名时,就只能应用 $ 占位符。应用#设置参数时,mybatis 会创立预编译的 sql 语句,预编译的 sql 语句执行效率高,并且能够避免 sql 注入攻打,在理论开发中,大部分状况下应用# 占位符。
- 介绍一下 Mybatis 的缓存机制?
mybatis 的缓存机制:一级缓存称为本地缓存,它默认启动,存在于 sqlSession 的生命周期中,他会把办法和入参计算之后生成一个 key 来存储缓存。二级缓存能够在配置文件 setting 中手动配置,默认敞开,在应用的时候在 Mapper.xml 文件中也须要加上标签。二级缓存存在与 SqlSessionFactory 中,他能够实现多个 sqlSession 缓存的共享,以名称空间为单位存储,咱们在开发的时候一班不应用二级缓存,因为它的弊大于利,例如在两个名称空间中都有对某个表的操作,一个名称空间改了,不会影响另一个的缓存,就会造成内存不统一。个别咱们会应用 redis 来实现缓存。
- 请你说说 mysql 索引,以及它们的益处和害处?
mysql 索引是一种帮忙疾速查找数据的数据结构,能够把它了解为书的目录,通过索引可能疾速找到数据所在位置。场景的索引数据结构有:Hash 表,通过 hash 算法疾速定位数据,但不适宜范畴查问,因为须要每个 key 都进行一次 hash、二叉树,查找和批改效率都比拟高,然而在 InnoDB 引擎中应用的索引是 B + Tree,相较于二叉树,B+ Tree 这种多叉树,更加矮宽,更适宜存储在磁盘中。应用索引减少了数据查找的效率,然而绝对的因为索引也须要存储到磁盘,所以减少了存储的压力,并且新增数据时须要同步保护索引。然而正当的应用索引可能极大进步咱们的效率。
- 请你讲讲 B 树和 B + 树?
B 树和 B + 树都是均衡多路查找树,B+ 树中,数据寄存在叶子节点中,其它节点寄存 key,而 B 树中,数据寄存在叶子节点和非叶子节点中。1. 因为 B + 树非叶子节点存储的是关键字,所以绝对与 b 树来说一页就能包容更多的关键字,b+ 树就会变得更宽更矮,从而读取关键字时就能缩小 io 次数,进步了查问效率;2. 因为 b + 树的叶子节点是通过链表链接的,并且是叶子节点有序的,所以在范畴查问时 b + 树只须要查找到范畴的上限而后遍历叶子节点就能失去整个范畴的记录;3.b+ 树的查问效率更加稳固,因为每次查问所走的门路长度都雷同,只须要从根节点查到叶子节点即可。
- 数据库为什么不必红黑树而应用 B + 树?
AVL 树和红黑树根本都是存储在内存中才会应用的数据结构。而数据库中的数据的索引会十分大,索引为了缩小内存的占用,索引会被存储到磁盘文件中,此时影响数据库查问效率的次要隐衷就是磁盘的 IO 次数。AVL 树和红黑树因为一个父节点只能存储两个子节点。所以应用 AVL 树或红黑树存储大规模数据时,树的深度就会很深,此时磁盘的 IO 次数也会大幅度减少。B+ 树中一个父节点有多个子节点,缩小了树的深度,磁盘 IO 次数也相应的缩小。
- 请你说说乐观锁和乐观锁?
乐观锁:乐观锁总是假如最好的状况,每次去拿数据的时候默认他人不会批改,所以不会上锁,只有当更新的时候会判断一个在此期间有没有更新了这个数据,实用于多读,能够应用版本号机制进行管制。乐观锁:乐观锁总是假如最坏的状况,每次去拿数据时都认为他人会批改,所以每次在拿数据时都会上锁,这个他人想拿这个数据时会阻塞直到拿到锁。mysql 数据库的共享锁和排他锁都是乐观锁的实现。
- 请你说说 mysql 的事务隔离级别?
事务的隔离级别有:未提交读、提交读、可反复读、串行化四种隔离级别。数据库多个事务同时执行时可能造成事务的一致性问题:脏读,不可反复读,幻读;提交读能够解决脏读的问题:脏读就是线程 A 批改一个数据没有提交,线程 B 读取了这个批改的数据之后线程 A 回滚,线程 B 读取到的数据就变成了脏数据。可反复读能够解决脏读和不可反复度的问题,不可反复读就是事务 A 屡次读取一个数据,事务 B 在 A 读取的过程中进行了批改,导致事务 A 屡次读取到的数据不统一。串行化能够同时解决三个问题,幻读就是事务 A 对一个表进行读取,事务 B 在 A 读取的时候增减或者删除数据,导读事务 A 读取到的数据并不统一。
- 说说聚簇索引和非聚簇索引?
它们最大的区别是索引和数据是否放在一起。聚簇索引:索引和数据放在一起,叶子节点保留数据行。非聚簇索引:索引和数据离开寄存,叶子节点寄存的是指向数据行的地址。
- 请你说说 mysql 的数据库引擎有哪些,各自有什么区别?
1.InnoDB 引擎是 mysql 的事务齐全存储引擎,具备提交、回滚和解体复原性能,反对行锁,增删改性能更优;2.MyISAM 引擎反对全文索引,只反对表级锁,通常用于只读或以读为主的场景,表占用空间较小;3.Memory 引擎是将所有数据都存储在 RAM 中,以便在须要疾速查找非关键数据的环境中进行快速访问,以前被称为 HEAP 引擎;4.Archive 引擎非常适合存储大量的独立的历史数据,领有高效的插入速度,查问反对较差。
- mysql 主从同步是如何实现的?
复制 replication 是 mysql 数据库提供的一种高可用高性能的解决方案,个别用来建设大型的利用。总的来说,replication 的工作原理分为以下 3 个步骤:1. 主服务器 master 把数据更改记录到二进制日志中 binlog 中;2. 从服务器 slave 把主服务器的二进制日志复制到本人的中继日志 relay log 中;3. 从服务器重做中继日志中的日志,把更改利用到本人的数据库上,以达到数据的最终一致性。
- 请你介绍以下数据库的 ACID?
原子性 A(atomicity):事务中的任何一个 sql 语句执行失败,那么整个事务都应该是失败的,曾经执行胜利的 sql 语句也应该回撤,数据库的状态也应该回到事务执行前的状态;一致性 C(consistency):事务将数据库从一种状态转变为另一种状态,在转换实现后,数据的完整性束缚并没有产生扭转;隔离性 I(isolation):每个事务读写操作的对象须要与其余事务读写操作事务对象互相拆散,即该事务提交前对其余事务都不可见;持久性 D(durability):事务一旦执行胜利,那么后果是永久性的,哪怕零碎产生谬误,数据库也能将数据恢复。
- 说说 redis 的数据结构?
redis 有五种根本数据类型 String、hash、list、set、zset 和三种非凡数据类型 geo、hyperloglog bitmap。String:底层是一个动静字符串,反对扩容,存储字符串;list:存储有序能够反复的元素,底层数据结构是双向链表 / 压缩链表;hash:存储的是键值对,底层是 ziplist 和 hash;set:存储的不可反复元素,底层数据结构能够是 hash 和整数数组;zset:存储的是有序的不可反复的元素,底层是 ziplist 和链表。
- 说说 redis 的长久化策略?
redis 的长久化形式有两种:RDB 和 AOF。RDB:它是通过数据集快照的形式来记录 redis 中的所有数据,在某个时间段内,将数据写入一个临时文件中,长久化完结,用这个临时文件替换上次的长久化文件,达到数据恢复。益处:只有一个 dump.rdb 文件,便于存储,容灾性较好,性能最大化,子过程来实现写操作,主过程持续解决命令。毛病:数据安全性低,RDB 是隔一段时间进行一次备份,在此期间,如果产生了异样,可能导致数据的不完整性。AOF:它是通过记录 redis 的所有命令,每执行一次就记录一次数据,保留在 AOF 文件中。长处:保障了数据的安全性和完整性,即使是中途宕机,也能够恢复过来。毛病:他的文件比 RDB 文件大,如果是数据集大的时候,它的复原速度比 RDB 文件慢。redis 默认是用 RDB 文件存储。
- 如何利用 redis 实现一个分布式锁?
分布式环境下会产生多个 server 并发批改一条数据的状况。因而须要分布式锁。咱们能够在 redis 中寄存一份代表锁的数据。最简略的形式就是 setnx key value 然而如果客户端遗记解锁就会造成死锁。如果给锁减少过期工夫,expire key second 会产生另一个问题,因为这两步并非原子性操作,如果第二部失败依然会呈现死锁问题。因而能够通过 set key value nx ex seconds 操作将两步封装成原子操作,解锁就是将代表锁的数据删除即可。但不能简略的 del key 因为如果过程 A 在没有执行结束时锁到期开释了,但进行 A 完结后依然会开释锁,这时候就会开释其余过程的锁。所以要给 key 赋一个随机值代表过程加个标识,过程 A 开释锁时进行判断是本人的再开释锁。另外开释这部分要保障原子性否则会死锁。能够应用 Lua 脚本将指令编排到一起,Lua 执行是原子性的。
- 说说缓存穿透、击穿、雪崩的区别?
缓存穿透:客户端拜访 redis 中不存在的数据,是的申请中转存储层,导致负载过大甚至宕机,起因可能是业务层误删了缓存或是有人歹意拜访不存在的数据。解决形式:1. 存储层未命中后,返回空指存入存储层,客户端再次拜访时,缓存层间接返回空值;2. 将数据存入布隆过滤器,拜访缓存之前经过滤器拦挡,若申请的数据不存在则间接返回空值。缓存击穿:一份热点数据,它的访问量十分大,在它缓存生效的霎时,大量申请中转存储层,导致服务解体。解决方案:1. 永不过期,对热点数据不设置过期工夫;2. 加互斥锁,当一个线程拜访该数据时,另一个线程只能期待,这个线程拜访之后,缓存中的数据将被重建,届时其余线程就能够从缓存中取值。缓存雪崩:大量数据同时过期,或是 redis 节点故障导致服务不可用,缓存层无奈提供服务,所有的申请中转存储层,造成数据库宕机。解决方案:1. 防止数据同时过期,设置随机过期工夫;2. 启用降级和熔断措施;3. 设置热点数据永不过期;4. 采纳 redis 集群,一个宕机,另外的还能用。
- redis 如何与数据库放弃双写一致性?
先更新数据库再删除缓存,缓存删除失败须要重试。
- 说说 redis 的单线程架构?
redis 采纳的是单线程 +IO 多路复用技术。这里的单线程指的是 redis 中读写操作和网路 IO 应用的是有一个线程来实现,然而其余操作是有其余线程实现,例如长久化操作。单线程既能够简化数据结构和算法的实现,同时也打消了线程切换和锁竞争所带来的耗费。redis 中采纳的 IO 多路复用技术实现了单线程下同时解决多个 IO 申请。redis 为生命这么块:1. 单线程进行读写操作,防止线程切换和锁竞争带来的耗费;2.redis 操作是在内存中进行的;3. 最重要的就是采纳了 IO 多路复用技术,实现了在网路 IO 中能都解决大量并发申请,实现高吞吐率。
- 如何实现 redis 的高可用?
主从复制:写肯定是在主服务器上,而后主服务器同步给从服务器。毛病:当主服务器挂掉的时候,不能主动切换到从服务器上。主从服务器存储数据一样,内存可用性差。长处:在肯定水平上分担主服务器读的压力。哨兵模式:构建多个哨兵节点监督主从服务器,当主服务器挂掉的时候,主动将对应的从服务器切换成主服务器。长处:实现主动切换,可用性高。毛病:主从服务器存储数据统一,内存可用性差。还要额定保护一套哨兵零碎,较为麻烦。集群模式:采纳无核心节点的形式实现。多个主服务器相连,一个主服务器能够有多个从服务器,不同的主服务器存储不同的数据。长处:可用性更高,内存可用性高。
- 说说 Redis 的主从同步机制?
主从同步分为全量同步和增量同步,从机第一次连贯主机时不会携带主机 id 和数据偏移量,主机会对从机的主机 id 进行校验,如果不是则阐明是第一次连贯须要进行全量同步,原理就是将以后数据写到 RDB 文件发送给从机,从机接管到文件之后将数据读取到从机的内存中,增量同步是第二次和之后连贯才产生,当从机第一次同步实现之后,主机在这期间数据发生变化,会将命令存储在缓冲区,当校验到从机的 id 正确是会获取从机的偏移量,从机从偏移量记录的命令开始将从机没同步的数据的操作命令发送给从机执行,执行实现后即实现了数据同步。
- 说说 redis 的缓存淘汰策略?
惰性删除:客户端拜访一个 Key 的时候,redis 先查看它的过期工夫,如果曾经过期了就立即删除这个 key。定期删除:redis 会将设置了过期工夫的 key 保留到一个字典外面,而后每过十秒就扫描一次。这个定期删除也不扫描字典中所有的 Key,而是采纳了一种简略的弹性策略。定期删除对内存更加敌对,而惰性删除对 CPU 更加敌对,所以 redis 采纳的是定期删除 + 惰性删除。