1、ArrayList 和 Vector 的区别。
Vector 是线程安全的,而 ArrayList 是线程序不安全的,如果只有一个线程会访问到集合,那最好是使用 ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用 Vector,因为不需要我们自己再去考虑和编写线程安全的代码;
2、Hashmap 实际上是一个数组和链表的结合体(在数据结构中,一般称之为 “链表散列 “)
3、Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用 == 还是equals()? 它们有何区别?
Set 里的元素是不能重复的,元素重复与否是使用 equals() 方法进行判断的
4、两个对象值相同 (x.equals(y) == true),但却可有不同的 hash code,这句话对不对?
不对。如果对象要保存在 HashSet 或 HashMap 中,它们的 equals 相等,那么,它们的 hashcode 值就必须相等。
5、HashSet 的底层实现是什么?
HashSet 的实现是依赖于 HashMap 的,HashSet 的值都是存储在 HashMap 中的。在 HashSet 的构造法中会初始化一个 HashMap 对象,HashSet 不允许值重复,因此,HashSet 的值是作为 HashMap 的 key 存储在HashMap 中的,当存储的值已经存在时返回 false。
6、数组 (Array)和列表(ArrayList)有什么区别?什么时候应该使用 Array 而不是ArrayList?
Array 可以包含基本类型和对象类型,ArrayList 只能包含对象类型。
Array 大小是固定的,ArrayList 的大小是动态变化的。
ArrayList 处理固定大小的基本数据类型的时候,这种方式相对比较慢。
7、简述 synchronized 和 java.util.concurrent.locks.Lock 的异同?
主要相同点:Lock 能完成 synchronized 所实现的所有功能。
主要不同点:Lock 有比 synchronized 更精确的线程语义和更好的性能。
synchronized 会自动释放锁,而 Lock 一定要求程序员手工释放,并且必须在 finally从句中释放。Lock 还有更强大的功能,例如,它的 tryLock 方法可以非阻塞方式去拿锁
8. run() 和 start() 区别。
run( ):只是调用普通 run 方法
start( ):启动了线程, 由 Jvm 调用 run 方法
启动一个线程是调用 start() 方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由 JVM 调度并执行。这并不意味着线程就会立即运行。
9、spring的bean加载流程,循环依赖
一: 实例化一个applicationContext的对象创建一个beanFactory工厂对象
二: beanFactory的后置处理器对当前的所有类进行扫描
三: 使用for循环将所有的类通过一个beanDefintion对象进行解析和初始化默认参数, 并 且将实例化后的对象缓存到beanDefintionMap中
四: 再次调用beanFactory的后置处理器对beanDefintion对象进行一些额外的扩展, 比方 说用户自定义实现的一些参数属性方法
五: Spring首先从singletonObjects (一 级缓存)中尝试获取,如果获取到了直接return
六: 如果获取不到并且对象在创建中,则尝试从earlySingletonObjects(二级缓存)中获 取,如果获取到了直接return
七: 如果还是获取不到并且允许从singletonFactories通过getObject获取,则通过 singletonFactory.getObject()(三级缓存)获取,如果获取到了就从singletonFactories中移 除,并且放进earlySingletonObjects (二级缓存)中
八: 如果三个缓存中都拿不到对象, spring会经过一 系列的验证并且 确定类的构造方法 后,调用类的构造方法通过反射实例化一个对象, 也就是createBean
九: 中间会经过非常多的判断,其中最关键的两个点是 是否需要注入属性,是否需 要生成代理对象
十: spring将创建好的bean存入到一级缓存singletonObject中, 此时一个bean的初始化 完成,随时可以被引用,根据用户业务做一些相关的操作
十一: 最后是销毁,在上下文初始化失败时,所有已经创建好的bean会销毁,或者当用 户关闭容器时,bean也会被销毁。除此之外,用户也可以自行调用destroy-类的方法手 动销毁一个bean
10、解释不同方式的自动装配 。
有五种自动装配的方式,可以用来指导 Spring 容器用自动装配方式来进行依赖注入。
· no:默认的方式是不进行自动装配,通过显式设置 ref属性来进行装配。
· byName:通过参数名 自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被设置成 byname,之后容器试图匹配、装配和该 bean 的属性具有相同名字的 bean。
· byType::通过参数类型自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被设置成 byType,之后容器试图匹配、装配和该 bean 的属性具有相同类型的 bean。如果有多个 bean 符合条件,则抛出错误。
· constructor:这个方式类似于 byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
· autodetect:首先尝试使用 constructor 来自动装配,如果无法工作,则使用 byType 方式
Spring Cloud之Ribbon与Nginx区别
Ribbon与Nginx区别
1.服务器端负载均衡Nginx
nginx是客户端所有请求统一交给nginx,由nginx进行实现负载均衡请求转发,属于服务器端负载均衡。
既请求由nginx服务器端进行转发。
2.客户端负载均衡Ribbon
Ribbon是从eureka注册中心服务器端上获取服务注册信息列表,缓存到本地,然后在本地实现轮训负载均衡策略。
既在客户端实现负载均衡。
应用场景的区别:
Nginx适合于服务器端实现负载均衡 比如Tomcat ,Ribbon适合与在微服务中RPC远程调用实现本地服务负载均衡,比如Dubbo、SpringCloud中都是采用本地负载均衡。
jdk 动态代理:
代理定义:
代理模式是指,为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用。
动态代理基于反射,
比如a要访问c,但是c拒绝a访问,
在a和c直接建立一个代理对象b,c是让b访问 的
a 访问 b 然后b再访问c,(b作为代理对象,类似于中介)
代理分为动态代理和静态代理
1、静态代理
定义一个接口
定义一个目标类,实现上面的接口
定义一个代理类
定义一个访问类
2、动态代理
动态代理:使用反射机制。在程序执行中。创建代理类对象。特点,不用创建类文件,代理的目标类是动态的,可设置的
动态代理的实现方式常用的有两种:使用JDK代理代理,通过CGLIB动态代理。
创建一个接口
接口的实现类
通过反射调用
核心地方
创建第二个实现类
调用第二个实现类方法