├── .DS_Store ├── README- MySQL.md ├── README-Java.md ├── README-Jvm.md ├── README-Micro.md ├── README-MulThread.md ├── README-Spring.md ├── README.md └── images ├── .DS_Store └── java └── hashmap-jdk1.8.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bage2014/interview/2c4e4b3c108114a1ecaafa554151f60958f45652/.DS_Store -------------------------------------------------------------------------------- /README- MySQL.md: -------------------------------------------------------------------------------- 1 | # MySQL # 2 | -------------------------------------------------------------------------------- /README-Java.md: -------------------------------------------------------------------------------- 1 | # Java 基础 # 2 | 3 | 知识点汇总github地址 [https://github.com/bage2014/interview](https://github.com/bage2014/interview) 4 | java基础代码实现demo地址[https://github.com/bage2014/study/tree/master/study-java/src/main/java/com/bage/study/java](https://github.com/bage2014/study/tree/master/study-java/src/main/java/com/bage/study/java) 5 | 6 | ## 面向对象理论基础 ## 7 | 8 | ### 面向对象的特征:继承、封装和多态 ### 9 | - 多态体现 10 | - 接口和接口之间的继承。 11 | - 类和类直接直接的继承。 12 | - 方法重载。 13 | - 方法重写。 14 | ### final、finally、finalize ### 15 | - final 16 | - java关键字 17 | - 被修饰的变量将不可重复赋值,只能在首次赋值 18 | - 被修饰的方法将不可以被重写 19 | - finally 20 | - try-catch-finally块之一,一般用来进行资源的释放 21 | - finalize 22 | - Java的析构函数 23 | 24 | ### Exception、Error ### 25 | - 继承关系 26 | 27 | 简单表示如下 28 | 29 | Throwable 30 | / \ 31 | Error Exception 32 | 33 | - 产生原因 34 | 35 | - Error 一般为系统错误,比如内存不够等,一般不需要程序进行处理 36 | - Exception 一般是用户的异常,比如空指针异常,可能需要程序研发人员进行捕获处理 37 | 38 | 39 | ### 运行时异常与一般异常 ### 40 | - 继承关系 41 | 42 | 简单表示如下 43 | 44 | Exception 45 | / \ 46 | xxxException RuntimeException 47 | 48 | - 两者差异 49 | - RuntimeException ,比如空指针异常,一般不需要程序研发人员进行捕获处理,但是可以避免,比如增加判断是否为null之后再进行业务操作 50 | - 常见的RuntimeException 51 | 1. NullPointerException - 空指针引用异常 52 | 2. ClassCastException - 类型强制转换异常 53 | 3. IllegalArgumentException - 传递非法参数异常 54 | 4. ArithmeticException - 算术运算异常 55 | 5. IndexOutOfBoundsException - 下标越界异常 56 | 6. NumberFormatException - 数字格式异常 57 | 58 | ### String、StringBuilder、StringBuffer ### 59 | - String 60 | 1. 字符串操作类,final类 61 | 2. 需要了解其常用方法和简单实现 62 | - StringBuilder 63 | 1. 字符串拼接类 64 | 2. 非线程安全 65 | - StringBuffer 66 | 1. 字符串拼接类 67 | 2. 线程安全,实现方式为在方法上加上synchronized关键字 68 | 69 | ### 重载和重写 ### 70 | - 重载,方法名一样,但是参数个数或参数类型不一样,比如print(int a)和print(String str) 71 | - 重写,子类重写父类中定义的方法,比如父类Parent类中存在print(int a)方法,但是子类重新对其进行了实现 72 | 73 | ### 抽象类和接口有什么区别 ### 74 | - 抽象类 75 | 1. Abstract 关键字修饰的class 76 | 2. 可以存在方法默认的实现 77 | - 接口 78 | 1. interface 关键字修饰 79 | 2. jdk8及之后版本,可以存在方法默认实现,jdk8之前必须为空方法,仅为方法声明 80 | 81 | ### int和Integer ### 82 | - Integer是int的包装类 83 | - Integer的值缓存范围[-128~127] 84 | 85 | ### 装箱和拆箱 ### 86 | 参考链接 [https://www.cnblogs.com/wang-yaz/p/8516151.html](https://www.cnblogs.com/wang-yaz/p/8516151.html) 87 | 88 | - 当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算 89 | - 它必须满足两个条件才为true == 类型相同 + 内容相同 90 | - Integer可能会抛出空指针异常。所以,有拆箱操作时一定要特别注意封装类对象是否为null 91 | 92 | ### 反射的用途及实现 ### 93 | 参考链接 [https://blog.csdn.net/snn1410/article/details/44978457](https://blog.csdn.net/snn1410/article/details/44978457)、[https://www.jianshu.com/p/d6035d5d4d12](https://www.jianshu.com/p/d6035d5d4d12) 94 | 95 | - 反射机制值得是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息 96 | - Java反射框架提供以下功能: 97 | 1. 在运行时判断任意一个对象所属的类 98 | 2. 在运行时构造任意一个类的对象 99 | 3. 在运行时判断任意一个类所具有的成员变量和方法(通过反射可以调用 private方法) 100 | 4. 在运行时调用任意一个对象的方法 101 | - 可以通过配置文件来动态配置和加载类,以实现软件工程理论里所提及的类与类,模块与模块之间的解耦。最重要的用途就是开发各种通用框架 102 | 103 | ### 常用的JDK包 ### 104 | - 基本类型,byte,int,char,double,float,boolean 105 | - 基本包装类,String、StringBuilder、Integer、BigInteger 106 | - 集合类,Map、Set、Table、List 107 | - 文件类,File等IO 108 | - 多线程的基本使用 109 | - 等等 110 | 111 | ### equals与== ### 112 | - equals比较内容,==比较地址 113 | - 字符串一定是需要Equals方法 114 | 115 | ### wait、notify方法放在Object里边? ### 116 | - 因为synchronized中的这把锁可以是任意对象,所以任意对象都可以调用wait()和notify();所以wait和notify属于Object。 117 | - 因为这些方法在操作同步线程时,都必须要标识它们操作线程的锁,只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法是定义在object类中。 118 | 119 | ### 线程间通信 ### 120 | 参考链接 [https://www.cnblogs.com/hapjin/p/5492619.html](https://www.cnblogs.com/hapjin/p/5492619.html) 121 | 122 | - 同步 123 | - while轮询的方式 124 | - wait/notify机制 125 | - 管道通信就是使用java.io.PipedInputStream 和 java.io.PipedOutputStream进行通信 126 | 127 | ### Java的平台无关性如何体现出来的 ### 128 | 129 | ### JDK和JRE的区别 ### 130 | 131 | 132 | ### hashCode和equals方法 ### 133 | - 重写equals必须重写hashcode 134 | - 当自定义对象作为集合类的key时,必须重写此两个方法 135 | 136 | ### Java序列化和反序列化 ### 137 | 参考链接 [https://blog.csdn.net/onceing/article/details/80969369](https://blog.csdn.net/onceing/article/details/80969369) 、[https://developer.ibm.com/zh/articles/j-lo-serial/]、[https://cloud.tencent.com/developer/article/1341385] 138 | 139 | - 基本概念 140 | 1. Serialization-序列化:可以看做是将一个对象转化为二进制流的过程 141 | 2. Deserialization-反序列化:可以看做是将对象的二进制流重新读取转换成对象的过程 142 | - 注意点 143 | 1. 若类仅仅实现了Serializable接口,则采用默认的序列化方式,对对象的非transient的实例变量进行序列化。ObjcetInputStream采用默认的反序列化方式,对对象的非transient的实例变量进行反序列化。 144 | 2. 若类不仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则ObjectOutputStream调用对象的writeObject(ObjectOutputStream out)的方法进行序列化。ObjectInputStream会调用对象的readObject(ObjectInputStream in)的方法进行反序列化。 145 | 3. 若类实现了Externalnalizable接口,且类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,则ObjectOutputStream调用对象的writeExternal(ObjectOutput out))的方法进行序列化。ObjectInputStream会调用对象的readExternal(ObjectInput in)的方法进行反序列化。 146 | 4. 被transient和static修饰的成员变量不会被序列化 147 | 5. 假设A实现了Serializable接口,且A为B的子类,B没有实现Serializable接口。那么在序列化和反序列话的时候,B的无参构造函数负责B的相关属性的序列化和反序列化。特殊的,当B没有无参构造函数的时候,将A对象进行序列化时不会报错,但是反序列化获取A的时候报错 148 | 6. 序列化时,只对对象的状态进行保存,而不管对象的方法 149 | 7. 当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口 150 | 8. 当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化 151 | 9. 并非所有的对象都可以序列化,至于为什么不可以,有很多原因了,比如:安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行RMI传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的;资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现; 152 | 10. 声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据。 153 | 11. 序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。为它赋予明确的值。显式地定义serialVersionUID有两种用途:在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。 154 | 12. Java有很多基础类已经实现了serializable接口,比如String,Vector等。但是比如HashTable就没有实现serializable接口; 155 | 13. 如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存!这是能用序列化解决深拷贝的重要原因; 156 | 157 | - 序列化步骤 158 | 1. 将对象实例相关的类元数据输出。 159 | 2. 递归地输出类的超类描述直到不再有超类。 160 | 3. 类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。 161 | 4. 从上至下递归输出实例的数据 162 | 163 | 164 | 165 | - 序列化 ID 的问题 166 | - 静态变量序列化 167 | - 父类的序列化与 Transient 关键字 168 | - 对敏感字段加密 169 | - 序列化存储规则 170 | 171 | 怎么实现Java的序列化 172 | 173 | 为什么实现了java.io.Serializable接口才能被序列化 174 | 175 | transient的作用是什么 176 | 177 | 怎么自定义序列化策略 178 | 179 | 自定义的序列化策略是如何被调用的 180 | 181 | ArrayList对序列化的实现有什么好处 182 | 183 | 184 | ### Java 8新特性 ### 185 | 参考链接 [http://www.runoob.com/java/java8-new-features.html](http://www.runoob.com/java/java8-new-features.html) 186 | 187 | - Lambda 表达式 − Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中,更详细的例子,请参考[被姜太公钓的鱼](https://blog.csdn.net/swh1314)的文章[https://blog.csdn.net/swh1314/article/details/82687052](https://blog.csdn.net/swh1314/article/details/82687052)。 188 | - 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。 189 | - 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。 190 | - 新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。 191 | - Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。 192 | - Date Time API − 加强对日期与时间的处理。 193 | - Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。 194 | - Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。 195 | 196 | ### 注解Annotation ### 197 | @interface 类型,包含 @Retention、@Target、@Document、@Inherited 四个元注解 198 | 199 | - @Retention 200 | - @Retention(RetentionPolicy.SOURCE) == 仅仅存在于源码中,但是在class字节码文件中不包含 201 | - @Retention(RetentionPolicy.CLASS) == 默认的保留策略,class字节码文件中存在,但运行时不存在 202 | - @Retention(RetentionPolicy.RUNTIME) == 在class字节码文件中存在,在运行时也存在 203 | 204 | - @Target 205 | - @Target(ElementType.TYPE) == 位于 接口、类、枚举、注解 206 | - @Target(ElementType.FIELD) == 位于 字段、枚举的常量 207 | - @Target(ElementType.METHOD) == 位于 方法上 208 | - @Target(ElementType.PARAMETER) == 位于 方法参数上 209 | - @Target(ElementType.CONSTRUCTOR) == 位于 构造函数上 210 | - @Target(ElementType.LOCAL_VARIABLE) == 位于 方法中的局部变量 211 | - @Target(ElementType.ANNOTATION_TYPE) == 位于 注解上 212 | - @Target(ElementType.PACKAGE) == 位于 包 213 | 214 | - @Documented 215 | - 存在于javadoc中 216 | - @Inherited 217 | - 可以被继承 218 | 219 | ### 对象引用 ### 220 | 对象引用分为四种类型,强引用、软引用、弱引用、虚引用,依次引用减弱 221 | 222 | - 强引用 223 | - 引用存在,则不会回收(大部分引用都是强引用,`String str = "abc"`) 224 | - 软引用 225 | - 内存溢出之前进行回收(`SoftReference sf = new SoftReference(obj)`) 226 | - 可以作用于类似缓存的功能,在内存不够,需要进行垃圾回收时候被回收 227 | - 弱引用 228 | - 第二次垃圾回收时回收(`WeakReference wf = new WeakReference(obj)`) 229 | - 可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记,用于监控对象 230 | - 虚引用 231 | - 每次垃圾回收时都会被回收(`PhantomReference pf = new PhantomReference(obj)`) 232 | - 可用于检测对象是否已经从内存中删除 233 | 234 | 235 | 236 | ## Java集合 list、map、set ## 237 | 238 | ### List 和 Set 区别 ### 239 | ### List 和 Map 区别 ### 240 | ### Arraylist 与 LinkedList 区别 ### 241 | ### ArrayList 与 Vector 区别 ### 242 | ### HashMap 和 Hashtable 的区别 ### 243 | ### HashSet 和 HashMap 区别 ### 244 | ### HashMap 和 ConcurrentHashMap 的区别 ### 245 | - HashMap不是线程安全的,ConcurrentHashMap则在某一个方法的执行上是线程安全的。 246 | - 数据结构 247 | 1. 都是数组+拉链实现的哈希表,但是具体实现上差别大了 248 | - 并发 249 | 1. Hashtable全表锁 250 | 2. HashMap多线程不安全,需要自己封装 251 | 3. ConcurrentHashMap加细粒度锁,读不加锁,如果读到空值再加锁。 252 | - null 253 | 1. Hashtable不允许用 null作为键和值 254 | 2. HashMap允许全局最多一个null键,但是允许无数个null值 255 | 3. ConcurrentHashMap不允许用 null作为键和值 256 | 257 | ### hashCode以及equals方法的联系 ### 258 | 259 | 260 | ### HashMap 的工作原理及代码实现 ### 261 | 参考链接 [https://blog.csdn.net/v123411739/article/details/78996181](https://blog.csdn.net/v123411739/article/details/78996181) 262 | 263 | 结构 264 | jdk 1.7数据结构 265 | hashmap-jdk1.7.png 266 | 267 | jdk 1.8数据结构 268 | hashmap-jdk1.8.png 269 | 270 | ### ConcurrentHashMap 的工作原理及代码实现 ### 271 | 272 | ### ConcurrentHashMap 常用方法 ### 273 | 274 | ### ConcurrentHashMap统计所有的元素个数 ### 275 | 276 | ### 多线程HashMap问题 ### 277 | -------------------------------------------------------------------------------- /README-Jvm.md: -------------------------------------------------------------------------------- 1 | # JVM 基础 # 2 | 3 | 知识点汇总github地址 [https://github.com/bage2014/interview](https://github.com/bage2014/interview) 4 | 5 | ## JVM理论基础 ## 6 | 7 | ### 内存划分 ### 8 | 9 | JVM规范,将内存分为 程序计数器、Java栈,也叫虚拟机栈、本地方法栈、方法区、堆 10 | 11 | | | | | | 12 | | ---- | ---- | ---- | ---- | 13 | | 线程私有 | 程序计数器 | Java虚拟机栈 | 本地方法区 | 14 | | 线程共享 | 方法区 | 堆 | | 15 | 16 | - 程序计数器 17 | 程序指令计数,从当前指令到下一个指令,从程序计数器获取下一个指令的地址,直到执行所有的指令;分支、循环、跳转都依赖于这个计数器实现; 18 | - Java虚拟机栈 19 | 用于保存方法栈帧,每调用一个方法,会新创建一个栈帧,当前的方法始终保持在栈帧的顶部;存储局部变量表、动态链接、方法出口等; 20 | - 本地方法栈 21 | 保存**本地方法**栈帧;与Java虚拟机栈类似; 22 | - 堆 23 | 保存对象,几乎所有的对象都在堆中分配;最主要的垃圾收集之处;可以细分为新生代、老年代;更可以细分为Eden空间、From Survivor空间和To Survivor空间;可以通过 -Xms控制最小堆空间,-Xmx控制最大堆空间 24 | - 方法区 25 | 保存类信息、常量、静态常量;运行时常量池,用于存放编译器生成的字面常量和符号引用 26 | 27 | ### 对象创建 ### 28 | 29 | 以hotspot 对象创建为例 30 | 31 | 1. 常量池中检查是否存在该类的符号引用?不存在,先执行类加载过程 32 | 2. 根据不同垃圾收集器的压缩整理功能,采用 “指针碰撞” 或 “空闲列表” 分配方式为新生对象进行内存分配 33 | 3. 内存分配过程中,要保证并发安全,采用CAS给内存分配过程加锁或将内存分配过程划分到每个线程的本地线程分配缓冲中进行;可以通过 -XX:+UseTLAB 参数控制; 34 | 4. 内存分配后,将分配到的内存空间初始化零值 35 | 5. 接下来,对对象的必要信息进行设置,包括对象属于哪个类的实例、对象哈希码、GC分代年龄等 36 | 6. 执行 方法,进行程序初始化的逻辑 37 | 38 | ### 对象内存分配过程 39 | 40 | 1. 尝试为Java对象在Eden中初始化内存区域 41 | 2. 当Eden空间够用时候,直接分配,过程到此结束 42 | 3. 否则,Jvm会释放在Eden中所有不活跃的对象(或大年龄对象) 43 | 4. 释放后Eden空间够用时候,直接分配,过程到此结束 44 | 5. 否则,Jvm将部分Eden中活跃对象放入Survivor区 45 | 6. 当Survivor区空间不够时,Survivor区的对象会被移到Old区 46 | 7. 当Old区空间不够时,JVM会在进行major collection 47 | 8. 垃圾收集后,若仍然无法存放活着的对象,导致JVM无法在Eden区为新对象创建内存区域,则出现内存溢出错误 48 | 49 | ### 对象内存结构 ### 50 | 51 | 以hotspot 对象创建为例 52 | 53 | | Java对象结构 | 说明 | 54 | | ------------ | ------------------------------------------------------------ | 55 | | 对象头 | Mark Word:对象自身运行时数据;比如哈希码、GC年龄、锁标志位等 | 56 | | | 类型指针:非必须;指向对象所属的类;对象的元数据信息;数组长度记录 | 57 | | 实例数据 | 对象的真正有效信息;父类子类信息都需要进行存储; | 58 | | 对齐填充 | 因对象大小必须是8的倍数,作对齐填充使用;非必须; | 59 | 60 | ### 对象访问方式 ### 61 | 62 | #### 句柄 63 | 64 | ​ Java 栈本地变量表 65 | 66 | ​ || 67 | 68 | ​ 句柄池 69 | 70 | ​ || 71 | 72 | 对象实例数据 + 对象类型数据 73 | 74 | 75 | 76 | #### 直接指针 77 | 78 | ​ Java 栈本地变量表 79 | 80 | ​ || 81 | 82 | 对象实例数据 + 对象类型指针 83 | 84 | ​ || 85 | 86 | ​ 对象类型数据 87 | 88 | #### 对比 89 | 90 | - 句柄;稳定,对象移动时,只会改变句柄中的实例数据指针,引用本身不修改 91 | - 直接指针;快!比如hotspot 就是使用直接指针方式 92 | 93 | ### 对象存活 ### 94 | 95 | 如何确认一个对象是否可以回收? 96 | 97 | #### 引用计数算法 #### 98 | 99 | - 基本思想 100 | 101 | 给对象设置一个引用计数器;每一个引用,计数器加一,失效时候,计数器减一;计数器等于零时候,表示可以回收 102 | 103 | - 优点 104 | 105 | 实现简单;效率高 106 | 107 | - 缺点 108 | 109 | 不能处理对象循环引用问题 110 | 111 | #### 可达性分析算法 #### 112 | 113 | - 基本思想 114 | 115 | 采用虚拟机栈、类引用对象、常量对象、本地方法引用对象作为根,从根节点向下搜索,判断跟节点到当前对象节点是否存在引用关系,不可达则认为不在引用,可以进行回收 116 | 117 | - 优点 118 | 119 | 可以解决对象循环引用问题 120 | 121 | - 缺点 122 | 123 | 实现难度较大些,效率低些 124 | 125 | #### 对象引用方式 #### 126 | 127 | 引用强度依次为:强引用 > 软引用 > 弱引用 > 虚引用 128 | 129 | jdk1.2之后,才开始出现了 软、弱、虚引用; 130 | 131 | - 强引用 132 | 133 | 普遍存在,最常见的引用;只要引用还在,jvm就不会回收;比如 Person p = new Person(); 134 | 135 | - 软引用 136 | 137 | 描述非必须的对象引用关系,在内存溢出之前被回收;比如 SoftReference obj = new SoftReference<>(someObj); 138 | 139 | - 弱引用 140 | 141 | 描述非必须的对象引用关系,在下一次垃圾回收时被回收;比如 WeakReference obj = new WeakReference<>(someObj); 142 | 143 | - 虚引用 144 | 145 | 最弱的对象引用关系,在对象被垃圾回收时时收到一个通知;虚引用必须和引用队列 (ReferenceQueue)联合使用,当对象被垃圾回收器准备回收时,则会把这个虚引用加入到与之关联的引用队列中;比如 PhantomReference obj3 = new PhantomReference<>(someObj,someQueue); 146 | 147 | 148 | 149 | ### 垃圾回收算法 ### 150 | 151 | - 标记清除算法 152 | 153 | 对要回收的对象,先进行标志,后进行清除;久之,会存在内存不连续;比如,一次垃圾回收,回收了,(0,1)和(0,3)和(0,5)三个位置,但是没有回收(0,2)和(0,4),那下次的内存,就无法使用(0,1)-(0,5)的连续空间;标记、清除的效率都不高; 154 | 155 | - 复制算法 156 | 157 | 为改进标记清除算法产生的内存碎片问题,对内存分为等大小两部分,交替回收其中一部分,存活的对象复制到另一部分空间;每次使用只能使用其中一半的内存,有点浪费,比如,内存分为,(0,1)-(0,3)和(0,3)-(0,5)两个部分,某次回收(0,1)-(0,3)空间,将存活对象拷贝到(0,3)-(0,5),而后在(0,1)-(0,3)分配对象;但是高效简单;适用于新生代,新生代属于朝生夕死,可以按照特定比例进行回收,比如 8 : 1 : 1 ;这样每次只浪费 10 % 的内存空间;同时,当真的出现了超过 10% 的对象存活,则使用老年代进行担保; 158 | 159 | - 标记整理算法 160 | 161 | 复制算法对于对象存活率较高的老年代,需要进行很多的复制,效率会降低;同时,存活对象也可能大于 50%,又没有其他的空间可以进行担保 ;老年代一般选取的是标记整理算法;对要回收的对象,先进行标志,后进行清除,然后,将存活的对象,进行整理,移动到边界位置,似的剩余空间连续;比如,一次垃圾回收,回收了,(0,1)和(0,3)和(0,5)三个位置,但是没有回收(0,2)和(0,4),然后,将(0,2)和(0,4)移动到(0,1)和(0,2),使得(0,3)-(0,5)的空间连续; 162 | 163 | - 分代整理算法 164 | 165 | 不算一种新的思想算法,仅仅是根据不同的场景,进行了分代收集,采取不同的手机算法进行组装,进而选择合适的回收算法;一般来说;年轻代(新生代)采用的是复制算法,老年代采用标记清除或标记整理算法 166 | 167 | #### 垃圾收集器 #### 168 | 169 | - Serial & Serial Old 170 | 171 | 单线程收集器; 172 | 173 | 对于单CPU来说,没有多线程交互开销,简单高效; 174 | 175 | JDK1.3之前的唯一垃圾收集器,历史最悠久; 176 | 177 | 在垃圾收集回收过程中,会暂停其他用户所有的线程工作; 178 | 179 | Serial 作用于新生代,采用复制算法; 180 | 181 | Serial Old 作用于老年代,采用标记整理算法; 182 | 183 | - ParNew 184 | 185 | Serial 的多线程版本; 186 | 187 | 仅仅适用于新生代,采用复制算法; 188 | 189 | 对于单CPU来说,使用无意义,不如直接使用Serial收集器; 190 | 191 | 在垃圾收集回收过程中,同样会暂停其他用户所有的线程工作; 192 | 193 | - Parallel Scavenge & Parallel Old 194 | 195 | 多线程收集; 196 | 197 | Parallel Scavenge 始于JDK1.4,作用于新生代,采用复制算法; 198 | 199 | Parallel Old 始于JDK1.6,作用于老年代,采用标记整理算法; 200 | 201 | 在垃圾收集回收过程中,同样会暂停其他用户所有的线程工作; 202 | 203 | 以吞吐量为设计关注点; 204 | 205 | -XX:MaxGCPauseMilis 控制最大垃圾停顿时间; 206 | 207 | -XX:GCTimeRatio 吞吐量大小设置; 208 | 209 | -XX:UseAdaptiveSizePolicy 虚拟机自适应策略开关; 210 | 211 | - CMS 212 | 213 | 以回收停顿时间为设计关注点; 214 | 215 | 仅仅适用于新生代,采用标记清除算法; 216 | 217 | 整体上说,因为耗时最长的并发标记和并发清除过程可以与用户线程并发执行,可以认为来回收过程可以于用户线程并发执行; 218 | 219 | 会存在一些不足,比如内存碎片、浮动垃圾、CPU敏感等 220 | 221 | - G1 222 | 223 | 224 | 225 | ### 类加载过程 ### 226 | jvm中class类的加载过程,大致分为这几个步骤 227 | 228 | 229 | 230 | 加载(load) 231 | - 根据全类名,加载class文件的二进制字节流;可以从 jar、war、网络、动态生成等方式加载 232 | - 将字节流转存到方法区,变成运行时数据结构 233 | - 内存中生成Class对象(比较特殊,在方法区中),并作为访问入口 234 | 235 | 验证(verify) 236 | - class的文件格式验证,验证是否符合JVM规范;开头、版本等等 237 | - class的元数据验证,验证是否符合Java语义;父类、接口、抽象类等等 238 | - class的字节码验证,验证数据流控制流不会危害JVM环境;类型转换、访问安全 239 | - 符号引用验证(在步骤 解析 中执行),类是否存在等等 240 | 241 | 准备(prepare) 242 | - 给变量分配内存 243 | - 初始化零值(比如int默认为0,boolean默认为false) 244 | - final变量直接赋值 245 | 246 | 解析 247 | - 符号引用变为直接引用 248 | - 类、字段、方法、接口方法解析 249 | 250 | 初始化 251 | - 初始化变量 252 | - 构造函数 253 | - static块 254 | 255 | 256 | ### 双亲委派机制 ### 257 | Java中,大概有三种类型加载器,启动类加载器(Bootstrap)<- 标准扩展类加载器(Extension)<- 应用程序类加载器(Application )<- 上下文类加载器(Custom),从右到左,尽量父类进行加载,当父类无法进行加载时候,才会使用子类进行加载 258 | 259 | - 意义 260 | - 防止同一个JVM,内存中出现两份class二进制字节码 261 | 262 | - 加载过程 263 | - 从已加载的类查找是否已经存在,存在不需要再次加载 264 | - 若不存在,则去parent中查找,存在不需要再次加载 265 | - 若不存在,递归在parent中查找,直到找到为止 266 | - 若找遍所有parent均不存在,且当前加载器已经没有parent加载器,则调用当前类加载器的findClass方法,如果能加载,结束 267 | - 如果不能,则递归返回child类加载器,继续调用findClass方法,如果能加载,结束 268 | - 如果找遍所有child的findClass方法,还是不能加载,则抛出异常 269 | 270 | - 破坏双亲委派机制 271 | - 将parent设为null 272 | - 重写load(String,boolean)方法,改变类的查找机制。 273 | 274 | ## JVM参数 ## 275 | 276 | - -Xms 277 | 278 | 堆初始值 50M,此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存 279 | 280 | ``` 281 | -Xms50m 282 | ``` 283 | 284 | 285 | 286 | - -Xmx 287 | 288 | 堆最大可用值 50M 289 | 290 | ``` 291 | -Xmx50m 292 | ``` 293 | 294 | xms 和 xmx 为什么要设置成一样? 295 | 296 | 设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小。 297 | 298 | 这两个值一般怎么赋值?多大合适? 299 | 300 | 301 | 302 | - -Xmn 303 | 304 | 新生代最大可用值1M 305 | 306 | ``` 307 | -Xmn1m 308 | ``` 309 | 310 | 整个堆大小 = 年轻代大小 + 年老代大小 + 持久代大小 311 | 312 | 313 | 314 | - -Xss 315 | 316 | 线程的私有栈大小1M 317 | 318 | ``` 319 | -Xss1m 320 | ``` 321 | 322 | 323 | 324 | - -XX:PrintGC 325 | 326 | 出发GC时,打印日志 327 | 328 | ``` 329 | -XX:+PrintGC 330 | ``` 331 | 332 | 333 | 334 | - -XX:PrintGCDetails 335 | 336 | 出发GC时,打印详细日志 337 | 338 | ``` 339 | -XX:+PrintGCDetails 340 | ``` 341 | 342 | 343 | 344 | ### 锁优化 ### 345 | 346 | #### 自旋锁自适应锁 #### 347 | 348 | 线程的挂起和恢复需要转到内核中进行,比较消耗性能,为提高性能,可以让程序自旋,不是放CPU,比如一个简单的循环等待 349 | 350 | 自适应的自旋锁,有虚拟机进行确定自旋的时间次数 351 | 352 | #### 锁消除 #### 353 | 354 | 对于明确不会存在线程安全问题的同步代码,JVM在即时编译会进行锁消除,忽略里面的同步 355 | 356 | #### 锁粗化 #### 357 | 358 | 对于频繁进行同步加锁和释放锁的片段,可以适当进行扩大锁的范围,避免每次进行锁的添加和释放 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | -------------------------------------------------------------------------------- /README-Micro.md: -------------------------------------------------------------------------------- 1 | # 微服务 # 2 | 3 | 知识点汇总github地址 [https://github.com/bage2014/interview](https://github.com/bage2014/interview) 4 | Spring 实践demo地址[https://github.com/bage2014/spring-study](https://github.com/bage2014/spring-study) 5 | 6 | 7 | ### 注册中心 ### 8 | 9 | #### 整体概述 #### 10 | 11 | - 基本说明 12 | 13 | ``` 14 | 微服务集群环境下,是各个服务的管理者,充当微服务架构中的通讯录角色 15 | 负责各个服务的信息记录,动态维护当前集群中的服务信息 16 | ``` 17 | 18 | - 角色组成 19 | 20 | ``` 21 | 服务提供者 : 专门给其他服务,提供服务,提供API 22 | 服务消费者 : 消费服务,调用服务提供者提供的API 23 | ``` 24 | 25 | - 常用操作 26 | - 服务注册 27 | - 服务续约 28 | - 服务下线 29 | - 拉取注册表 30 | 31 | #### 服务高可用 #### 32 | 33 | #### 服务注册过程 #### 34 | 35 | #### 服务续约过程 #### 36 | 37 | #### 服务下线过程 #### 38 | 39 | #### 服务剔除过程 #### 40 | 41 | #### 服务保护模式 #### 42 | 43 | #### 服务同步过程 #### 44 | 45 | #### 客户端服务拉群过程 #### 46 | 47 | #### 客户端优雅关闭服务 #### 48 | 49 | ### 常用组件 50 | 51 | #### Eureka 52 | 53 | #### Consul 54 | 55 | #### ZooKeeper -------------------------------------------------------------------------------- /README-MulThread.md: -------------------------------------------------------------------------------- 1 | # Java 多线程 # 2 | 3 | 知识点归类github地址 [https://github.com/bage2014/interview](https://github.com/bage2014/interview) 4 | 多线程代码demo实现github地址[https://github.com/bage2014/study/tree/master/study-java/src/main/java/com/bage/study/java/multhread](https://github.com/bage2014/study/tree/master/study-java/src/main/java/com/bage/study/java/multhread) 5 | 6 | to be continue! 提纲已经就绪,会不断进行完善!!! 7 | 8 | ## 多线程理论基础 ## 9 | 10 | ### 什么是多线程 ### 11 | 12 | ### 线程和进程 ### 13 | 14 | ### 线程安全 ### 15 | 16 | ### 重入锁 ### 17 | 18 | ### 死锁的四个条件 ### 19 | - 互斥 20 | - 请求与保持 21 | - 不剥夺 22 | - 循环等待 23 | 24 | ### 预防死锁 ### 25 | 26 | ### 检查死锁 ### 27 | - Jconsole查看死锁 28 | - Jstack查看死锁 29 | 30 | ### volatile ### 31 | - JMM 32 | - 内存可见性 33 | - 防止指令重排序 34 | - 不能保证原子性 35 | 36 | Java 中读取 long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位) 37 | 38 | ### synchronized ### 39 | 40 | - 作用 41 | 1. 互斥访问 42 | 2. 内存可见性 43 | 3. 防止指令重排序 44 | 45 | - 用法 46 | 1. 修饰普通方法 47 | 2. 修饰静态方法 48 | 3. 修饰代码块 49 | 50 | - 注意点 51 | 1. 当一个线程在访问对象的 synchronized 方法,因为对象只有一把锁,其他线程无法获取该对象的锁,所以无法访问该对象的其他synchronized实例方法,但是其他线程还是可以访问该实例对象的其他非synchronized方法 52 | 2. 实现原理为,对象监视器,Monitor 53 | 54 | ### volatile vs synchronized vs lock ### 55 | 56 | - 来源差异 57 | 58 | volatile、synchronized为Java关键字; 59 | lock是Java类 60 | 61 | - 代价开销 62 | 63 | volatile不是锁,代价最小; 64 | lock是一般基于AQS,相对比synchronized代价小; 65 | synchronized代价最大 66 | 67 | - 简单性 68 | 69 | volatile、synchronized为Java关键字,JVM全权帮忙维护,只要我们能正确使用,不需要我们太多关心维护; 70 | lock是Java类,有很多方法可以调用,灵活性最好,但是需要自己控制锁的获取、释放 71 | 72 | 73 | ### 进程间通信 ### 74 | - 管道pipe 75 | - 命名管道FIFO 76 | - 消息队列MessageQueue 77 | - 共享存储SharedMemory 78 | - 信号量Semaphore 79 | - 套接字Socket 80 | - 信号 ( sinal ) 81 | 82 | ### 并发和并行 ### 83 | 84 | ### 创建线程 ### 85 | - 集成Thread类 86 | - 实现Runable接口 87 | - 实现Callable接口 88 | 89 | ### Object的wait、notify方法 ### 90 | 91 | ### sleep、 await方法差别### 92 | 93 | ## 多线程常用类 ## 94 | 参考地址 [http://www.importnew.com/21889.html](http://www.importnew.com/21889.html) 95 | ### Thread ### 96 | 97 | 98 | ### CAS ### 99 | - ABA问题 100 | - 原子性问题 101 | 102 | 锁自旋,CPU 问题 103 | ### 原子操作类 ### 104 | 105 | 106 | ### CountDownLatch ### 107 | - 某线程需要等待多个线程执行完毕,再执行。 108 | - 实现多个线程共同等待,同时开始执行任务,不可重用。(此类似于CyclicBarrier,可重用) 109 | 110 | ### CyclicBarrier ### 111 | - CyclicBarrier允许一组线程互相等待,直到到达某个公共屏障点。 112 | - 与CountDownLatch不同的是该barrier在释放等待线程后可以重用,所以称它为循环(Cyclic)的屏障 113 | 114 | ### CountDownLatch、CyclicBarrier差别 ### 115 | - CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: 116 | CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行; 117 | 而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行; 118 | - CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。 119 | 120 | ### Semaphore ### 121 | - Semaphore是一个计数信号量,它的本质是一个”共享锁”。 122 | - 信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。 123 | - Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权限。 124 | 125 | ### Exchanger ### 126 | - 用于进行线程间的数据交换。 127 | - 两个线程通过exchange方法交换数据 128 | - 该工具类的线程对象是成对的 129 | 130 | ### ThreadLocal ### 131 | 参考链接 [https://blog.csdn.net/u012088516/article/details/84067841](https://blog.csdn.net/u012088516/article/details/84067841)、[https://blog.csdn.net/bntx2jsqfehy7/article/details/78315161](https://blog.csdn.net/bntx2jsqfehy7/article/details/78315161) 132 | 133 | - 每个Thread 维护一个 ThreadLocalMap 映射表,这个映射表的 key 是 ThreadLocal实例本身,value 是真正需要存储的 Object。 134 | - ThreadLocal 本身并不存储值,它只是作为一个 key 来让线程从 ThreadLocalMap 获取 value。值得注意的是图中的虚线,表示 ThreadLocalMap 是使用 ThreadLocal 的弱引用作为 Key 的,弱引用的对象在 GC 时会被回收。 135 | - ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal没有外部强引用来引用它,那么系统 GC 的时候,这个ThreadLocal势必会被回收,这样一来,ThreadLocalMap中就会出现key为null的Entry,就没有办法访问这些key为null的Entry的value,如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:`Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value`永远无法回收,造成内存泄漏。 136 | - ThreadLocal里面使用了一个存在弱引用的map, map的类型是ThreadLocal.ThreadLocalMap. Map中的key为一个threadlocal实例。这个Map的确使用了弱引用,不过弱引用只是针对key。每个key都弱引用指向threadlocal。 当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收。 137 | 但是,我们的value却不能回收,而这块value永远不会被访问到了,所以存在着内存泄露。因为存在一条从current thread连接过来的强引用。只有当前thread结束以后,current thread就不会存在栈中,强引用断开,Current Thread、Map value将全部被GC回收。最好的做法是将调用threadlocal的remove方法,这也是等会后边要说的。 138 | - 使用static的ThreadLocal,延长了ThreadLocal的生命周期,可能导致内存泄漏。 139 | - 分配使用了ThreadLocal又不再调用get(),set(),remove()方法,那么就会导致内存泄漏,因为这块内存一直存在。 140 | 141 | ### 线程池 ### 142 | 参考链接 [https://www.cnblogs.com/dongguacai/p/6030187.html](https://www.cnblogs.com/dongguacai/p/6030187.html)、[https://www.cnblogs.com/szwh/p/7761171.html](https://www.cnblogs.com/szwh/p/7761171.html)、[https://blog.csdn.net/shahuhubao/article/details/80311992](https://blog.csdn.net/shahuhubao/article/details/80311992)、[https://justsee.iteye.com/blog/999189](https://justsee.iteye.com/blog/999189) 143 | 144 | #### 构造函数参数 #### 145 | 146 | int corePoolSize = 2; // 核心线程池大小 147 | int maximumPoolSize = 5; // 最大线程池大小 148 | long keepAliveTime = 10; // 线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程有效时间 149 | TimeUnit unit = TimeUnit.SECONDS; // keepAliveTime时间单位 150 | BlockingQueue workQueue; // 阻塞任务队列 151 | ThreadFactory threadFactory; // 新建线程工厂 152 | RejectedExecutionHandler handler; // 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理 153 | 154 | | **参数** | **说明** | 155 | | --------------- | ------------------------------------------------------------ | 156 | | corePoolSize | 核心线程池大小 | 157 | | maximumPoolSize | 最大线程池大小 | 158 | | keepAliveTime | 线程池中超过corePoolSize时空闲线程的最大存活时间 | 159 | | unit | keepAliveTime的时间单位 | 160 | | workQueue | 阻塞任务队列 | 161 | | threadFactory | 线程工厂 | 162 | | handler | 当提交任务数超过(maximumPoolSize+workQueue)时,任务会交给handler来处理 | 163 | 164 | 165 | 166 | #### BlockingQueue阻塞队列 #### 167 | 168 | - ArrayBlockingQueue 169 | 170 | 基于数组实现的一个阻塞队列,在创建ArrayBlockingQueue对象时必须制定容量大小。并且可以指定公平性与非公平性,默认情况下为非公平的,即不保证等待时间最长的队列最优先能够访问队列。 171 | 172 | - LinkedBlockingQueue 173 | 174 | 基于链表实现的一个阻塞队列,在创建LinkedBlockingQueue对象时如果不指定容量大小,则默认大小为Integer.MAX_VALUE。 175 | 176 | - PriorityBlockingQueue[praɪˈɒrəti] 177 | 178 | 以上2种队列都是先进先出队列,而PriorityBlockingQueue却不是,它会按照元素的优先级对元素进行排序,按照优先级顺序出队,每次出队的元素都是优先级最高的元素。注意,此阻塞队列为无界阻塞队列,即 179 | 容量没有上限(通过源码就可以知道,它没有容器满的信号标志),前面2种都是有界队列。 180 | 181 | - DelayQueue 182 | 183 | 基于PriorityQueue,一种延时阻塞队列,DelayQueue中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue也是一个无界队列,因此往队列中插入数据的操作(生产者)永远不会 184 | 被阻塞,而只有获取数据的操作(消费者)才会被阻塞。 185 | 186 | #### RejectedExecutionHandler拒绝策略 #### 187 | 超出线程范围和队列容量的任务的处理程序 188 | 189 | - ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出(默认)RejectedExecutionException异常。 190 | - ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 191 | - ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程) 192 | - ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 193 | 194 | #### 提交过程 #### 195 | 196 | 1. 校验当前执行的线程数,是否小于 corePoolSize ,小于corePoolSize,则创建一个线程执行任务 197 | 2. 否则,尝试添加到阻塞队列中,如果能够添加,则提交过程结束 198 | 3. 否则,如果阻塞队列已经无法添加,则校验当前线程数是否达到maximumPoolSize个数,如果没有达到,创建新线程执行任务 199 | 4. 否则,如果已经达到maximumPoolSize个数,此时采取RejectedExecutionHandler拒绝策略进行拒绝操作 200 | 201 | - 源代码 202 | 203 | public void execute(Runnable command) { 204 | if (command == null) 205 | throw new NullPointerException(); 206 | int c = ctl.get(); 207 | if (workerCountOf(c) < corePoolSize) { 208 | if (addWorker(command, true)) 209 | return; 210 | c = ctl.get(); 211 | } 212 | if (isRunning(c) && workQueue.offer(command)) { 213 | int recheck = ctl.get(); 214 | if (! isRunning(recheck) && remove(command)) 215 | reject(command); 216 | else if (workerCountOf(recheck) == 0) 217 | addWorker(null, false); 218 | } 219 | else if (!addWorker(command, false)) 220 | reject(command); 221 | } 222 | 223 | #### excute vs submit #### 224 | - excute 无返回值,submit有返回值 225 | - submit里面还是调用了excute方法 226 | 227 | #### shutdown vs shutdownnow #### 228 | - shutDown() 229 | 1. 线程池的状态编程SHUTDOWN 230 | 2. 不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。 231 | 3. 此时线程池不会立刻退出,会把线程池中的任务都已经处理完成,才会退出。 232 | 233 | - shutdownNow() 234 | 1. 线程池的状态立刻变成STOP状态,并通过调用Thread.interrupt()方法试图停止所有正在执行的线程,不再处理还在池队列中等待的任务 235 | 2. 它会返回那些未执行的任务。 236 | 3. ShutdownNow()并不代表线程池就一定立即就能退出,它可能必须要等待所有正在执行的任务都执行完成了才能退出。 237 | 238 | #### 线程池状态 #### 239 | Running、ShutDown、Stop、Tidying、Terminated 240 | 241 | ### 线程池默认4个实现类 ### 242 | 243 | ### AQS ### 244 | 245 | ### 偏向锁、轻量级锁、重量级锁、自旋锁 ### 246 | -------------------------------------------------------------------------------- /README-Spring.md: -------------------------------------------------------------------------------- 1 | # Java 基础 # 2 | 3 | 知识点汇总github地址 [https://github.com/bage2014/interview](https://github.com/bage2014/interview) 4 | Spring 实践demo地址[https://github.com/bage2014/spring-study](https://github.com/bage2014/spring-study) 5 | 6 | ## Spring 理论基础 ## 7 | 8 | ### 谈谈你对Spring的理解 ### 9 | 关键点 10 | - 企业框架,目前最流行,没有之一 11 | - AOP、IOC、Spring MVC 12 | 13 | ### Spring中用到了哪些设计模式 ### 14 | - 工厂模式,比如 BeanFactory 15 | - 代理模式,在Aop实现中用到了JDK的动态代理 16 | - 单例模式,Bean的创建默认就是单利的 17 | 18 | ### IoC的启动过程 ### 19 | - Resource文件的定位,即找到bean的配置文件 20 | - 通过特定的reader解析该bean配置文件,抽象成beanDefinition类 21 | - 将beanDefinition向容器注册,写入到一个大的HashMap中 22 | 23 | 24 | ### Spring 容器启动过程 ### 25 | 26 | 27 | ### BeanFactory 和 ApplicationContext 区别 ### 28 | 参考链接:[https://blog.csdn.net/lxyso/article/details/45446757](https://blog.csdn.net/lxyso/article/details/45446757)、[https://www.cnblogs.com/aspirant/p/9082858.html](https://www.cnblogs.com/aspirant/p/9082858.html) 29 | 30 | - 功能,BeanFactory负责读取bean配置,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的声明周期;ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了国际化支持、资源访问、事件传递、队Web的支持等功能 31 | - BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化;而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。 32 | - BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册 33 | 34 | ### Bean 的生命周期 ### 35 | 代码实现 [https://github.com/bage2014/study/tree/master/study-spring/src/main/java/com/bage/lifecircle](https://github.com/bage2014/study/tree/master/study-spring/src/main/java/com/bage/lifecircle) 36 | 37 | 1. 实例化一个Bean,也就是我们通常说的new 38 | 2. 按照Spring上下文对实例化的Bean进行配置,也就是IOC注入 39 | 3. 如果这个Bean实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的是Spring配置文件中Bean的ID 40 | 4. 如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(),传递的是Spring工厂本身(可以用这个方法获取到其他Bean) 41 | 5. 如果这个Bean实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文,该方式同样可以实现步骤4,但比4更好,以为ApplicationContext是BeanFactory的子接口,有更多的实现方法 42 | 6. 如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用After方法,也可用于内存或缓存技术 43 | 7. 如果这个Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法 44 | 8. 如果这个Bean关联了BeanPostProcessor接口,将会调用postAfterInitialization(Object obj, String s)方法 45 | 注意:以上工作完成以后就可以用这个Bean了,那这个Bean是一个single的,所以一般情况下我们调用同一个ID的Bean会是在内容地址相同的实例 46 | 9. 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean接口,会调用其实现的destroy方法 47 | 10. 最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法 48 | 49 | ### Bean的作用域 ### 50 | 51 | - **singleton**(默认): 在Spring的IoC容器中只存在一个对象实例,所有该对象的引用都共享这个实例。Spring 容器只会创建该bean定义的唯一实例,这个实例会被保存到缓存中,并且对该bean的所有后续请求和引用都将返回该缓存中的对象实例,一般情况下,无状态的bean使用该scope。 52 | - **prototype**:每次对该bean的请求都会创建一个新的实例,一般情况下,有状态的bean使用该scope。 53 | - **request**:每次http请求将会有各自的bean实例,类似于prototype。 54 | - **session**:在一个http session中,一个bean定义对应一个bean实例。 55 | - **global session**:在一个全局的http session中,一个bean定义对应一个bean实例。典型情况下,仅在使用portlet context的时候有效。 56 | 57 | ### AOP ### 58 | 59 | #### 实现原理 #### 60 | 默认,接口基于JDK动态代理,类为cglib 61 | 62 | #### 注意事项 #### 63 | - 嵌套失效问题 64 | - final类直接报错问题(动态代理的实现原理) 65 | 66 | ### Spring 事务 ### 67 | 68 | #### 实现原理 #### 69 | 基于AOP,所以,嵌套的事务会失效 70 | 71 | #### 传播机制 #### 72 | - 1 73 | - 2 74 | - 3 75 | - 4 76 | 77 | ### Spring MVC ### 78 | #### 请求过程 #### 79 | 1. 用户请求DispatchServlet 80 | 2. DispatchServlet根据请求路径调用具体HandlerMapping返回一个HandlerExcutionChain 81 | 3. DispatchServlet调用HandlerAdapter适配器 82 | 4. HandlerAdapter调用具体的Handler处理业务 83 | 5. Handler处理结束返回一个具体的ModelAndView给适配器 84 | 6. 适配器将ModelAndView给DispatchServlet 85 | 7. DispatchServlet把视图名称给ViewResolver视图解析器 86 | 8. ViewResolver返回一个具体的视图给DispatchServlet 87 | 9. 渲染视图,展示给用户 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java 面试知识点总结 2 | Java面试知识点总结,会不断进行完善,1个月内将下面的列的提纲补充完整,同时包含部分答案,仅供参考使用 3 | 4 | ## [Java 基础](https://github.com/bage2014/interview/blob/master/README-Java.md) ## 5 | 面向对象理论,基础知识; 6 | 7 | char、int、boolean、double、byte、long等基础数据类型; 8 | 9 | Integer、String等包装类型; 10 | 11 | array、list、map、set、table、等java数据结构; 12 | 13 | String、StringBuilder、StringBuffer等字符串操作类; 14 | 15 | Java反射; 16 | 17 | Java异常体系; 18 | 19 | JDK各个版本特性; 20 | 21 | 序列化和反序列化; 22 | 23 | 静态代理和动态代理; 24 | 25 | ## 数据库 ## 26 | 理论知识,前世今生; 27 | 28 | 主流数据库特性对比; 29 | 30 | 三大范式; 31 | 32 | 数据库索引; 33 | 34 | 索引结构原理; 35 | 36 | innerDB等; 37 | 38 | 索引优化; 39 | 40 | 集群; 41 | 42 | 事物; 43 | 44 | binlog、redolog、undolog等 45 | 46 | ## 数据结构 ## 47 | 常用数据结构 48 | 49 | array、list、set、stack、queue、tree、graph; 50 | 51 | 跳跃表、 52 | 53 | Bitmap 54 | 55 | ## 常用算法 ## 56 | 查找; 57 | 58 | 排序; 59 | 60 | 暴力法; 61 | 62 | 贪心; 63 | 64 | 递归与分治; 65 | 66 | 回溯; 67 | 68 | 动态规划; 69 | 70 | ## [多线程](https://github.com/bage2014/interview/blob/master/README-MulThread.md) ## 71 | 线程的理论知识; 72 | 73 | 线程创建、执行等常用方法; 74 | 75 | 线程状态,线程池状态以及转化; 76 | 77 | AtomicInteger、AtomicXXX; 78 | 79 | CountdownLatch、CyclicBarrier; 80 | 81 | Semaphore、ThreadLocal; 82 | 83 | CAS 比较交换思路; 84 | 85 | 锁机制,独占锁、非独占锁; 86 | 87 | AQS抽象队列同步器; 88 | 89 | 线程池; 90 | 91 | CompletableFuture; 92 | 93 | ## [JVM](https://github.com/bage2014/interview/blob/master/README-Jvm.md) ## 94 | 常用理论知识,前世今生,开源组件; 95 | 96 | JVM内存划分; 97 | 98 | JMM; 99 | 100 | 对象存活判断; 101 | 102 | 常用GC算法; 103 | 104 | GC触发原因; 105 | 106 | 垃圾收集器; 107 | 108 | 类加载过程; 109 | 110 | 常用命令,参数调优; 111 | 112 | ## 性能优化 ## 113 | 114 | CPU、Memory、Disk、Network等指标; 115 | 116 | QPS、TPS等性能指标; 117 | 118 | Jps、Jmap、Jstack等常用命令; 119 | 120 | GC日志、Dump等分析; 121 | 122 | 开源分析工具; 123 | 124 | ## Mybatis ## 125 | MyBatis核心类以及原理; 126 | 127 | 一级缓存、二级缓存; 128 | 129 | 常用配置; 130 | 131 | 常用标签; 132 | 133 | 动态SQL; 134 | 135 | 插件; 136 | 137 | 一对多、多对多等 138 | 139 | ## [Spring](https://github.com/bage2014/interview/blob/master/README-Spring.md) ## 140 | 基本使用; 141 | 142 | Spring 启动过程; 143 | 144 | Bean声明周期; 145 | 146 | IoC原理; 147 | 148 | Aop原理; 149 | 150 | 事务实现原理; 151 | 152 | 事务传播机制; 153 | 154 | 事务隔离级别; 155 | 156 | MVC请求过程; 157 | 158 | Spring Boot 、Spring、Spring Cloud体系 159 | 160 | 个性化改造 161 | 162 | ## 设计模式 ## 163 | 常用设计模式; 164 | 165 | 实现; 166 | 167 | 开源中的实现; 168 | 169 | 动态代理(重点说明); 170 | 171 | ## web知识 ## 172 | session、cookie; 173 | 174 | servlet声明周期; 175 | 176 | listener、filter、servlet的启动顺序; 177 | 178 | 转发、重定向; 179 | 180 | request、response; 181 | 182 | ## redis ## 183 | 集群; 184 | 185 | [分布式锁](https://github.com/bage2014/study/blob/master/study-redis/README-distribute-lock.md) 186 | 187 | 缓存组件对比; 188 | 189 | 底层数据类型结构; 190 | 191 | 快的原理 192 | 193 | 备份策略; 194 | 195 | 淘汰策略; 196 | 197 | 手写简约版; 198 | 199 | ## Tomcat ## 200 | 框架 201 | 202 | 启动过程 203 | 204 | 优化配置 205 | 206 | ## web安全 ## 207 | - XSS攻击 208 | - SQL注入攻击 209 | - 权限 210 | - SCRF攻击 211 | - HTTPS 212 | 213 | ## 分布式 ## 214 | - 集群 215 | - CAP理论、BASE理论 216 | - Spring Cloud VS dubbo 217 | - 分布式主键 218 | - 分布式锁 219 | - 分布式事务 220 | - 一致性Hash 221 | - 幂等性 222 | 223 | ## Spring Cloud ## 224 | - 注册中心 225 | - 网关 226 | - 配置中心 227 | - 负载均衡 228 | - 熔断 229 | - 限流 230 | - 分布式事务 231 | 232 | ## Linux ## 233 | - 常用命令 234 | - docker 235 | 236 | 237 | 238 | -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bage2014/interview/2c4e4b3c108114a1ecaafa554151f60958f45652/images/.DS_Store -------------------------------------------------------------------------------- /images/java/hashmap-jdk1.8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bage2014/interview/2c4e4b3c108114a1ecaafa554151f60958f45652/images/java/hashmap-jdk1.8.png --------------------------------------------------------------------------------