JAVA面试笔记
JAVA面试笔记Java基础面试1、HashMap源码?5、Set的实现?6、讲解线程execute?8、讲解Runable和Callnable的区别?9、使用泛型的好处?10、JDK动态代理和Cglib的区别?Spring面试题Spirng基础面试1、什么是Spring?2、使用Spring的好处?3、Spring由哪些模块组成?4、核心容器(应用上下文) 模块。5、 BeanFactory –
JAVA面试笔记
- Java基础面试
- Spring面试题
- Spirng基础面试
- 1、什么是Spring?
- 2、使用Spring的好处?
- 3、Spring由哪些模块组成?
- 4、核心容器(应用上下文) 模块。
- 5、 BeanFactory – BeanFactory 实现举例?
- 6、Spring加载流程?
- 7、SpringMVC请求流程?
- 8、简述Spring中Bean的声明周期?
- 10、使用Spring boot的好处?
- 11、Spring boot 加载配置顺序?
- 12、对Spring cloud微服务的理解?
- 13、讲讲 Spring 事务的传播属性?
- 14、Spring 如何管理事务的?
- 15、Spring 怎么配置事务(具体说出一些关键的 xml 元素)?
- 16、说说你对 Spring 的理解,非单例注入的原理?它的生命周期?循环注入的原理, aop 的实现原理,说说 aop 中的几个术语,它们是怎么相互工作的?
- 17、BeanFactory和ApplicationContext有什么区别?
- 18、你对Spring核心组件的理解?
- 19、简述Bean的生命周期?
- 20、@AspectJ 的用法?
- 21、SpringBoot比Spring做了哪些改进?
- 22、你如何理解 Spring Boot 中的 Starters?
- 23、SpringIOC是什么?DI是什么 优点是什么?
- 第三方中间件
- 数据库
Java基础面试
1、HashMap源码?
<key, value>
形式存储,可以保证唯一。基础实现是通过Node{key,value, next},next指的是一个Entry存储对应的下一个Entry。链表结构形式。
-
hashMap存储数据结构
-
JDK1.8之前是数组+链表
-
JDK1.8开始是数组+l链表+红黑树
当数组中某个链表长度大于8之后是转换成红黑树存储,小于8用的是链表存储。
-
-
key是如何保证唯一性的
对key使用hash函数,确保唯一性。hash(key) % 16能够判断落到哪个数组中。hashmap实现用的是 15 & hash(key)位运算,和取模是一个效果,但是计算效率更高。
-
put操作
通过key来确定是否重复,key重复则直接替换原有的value,不重复则追加到当前链表的末端。
-
get操作
对key进行hash获取hash值,定位的数组中,在对链表或红黑树查询取值。
5、Set的实现?
底层实现是Hashmap。
6、讲解线程execute?
线程池的submit和execute方法区别
- 接收的参数不一样
- submit有返回值,而execute没有
- submit方便Exception处理
8、讲解Runable和Callnable的区别?
Callable接口和Runnable接口相似,区别就是Callable需要实现call方法,而Runnable需要实现run方法;并且,call方法还可以返回任何对象,无论是什么对象。
9、使用泛型的好处?
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
- 类型安全 泛型的主要目标是实现java的类型安全。 泛型可以使编译器知道一个对象的限定类型是什么,这样编译器就可以在一个高的程度上验证这个类型
- 消除了强制类型转换 使得代码可读性好,减少了很多出错的机会
- 在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
10、JDK动态代理和Cglib的区别?
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
- 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
JDK动态代理和CGLIB字节码生成的区别
(1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final
Spring面试题
Spirng基础面试
1、什么是Spring?
2、使用Spring的好处?
- 轻量:Spring 是轻量的,基本的版本大约2MB。
- 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
- 面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
- 容器:Spring 包含并管理应用中对象的生命周期和配置。
- MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
- 事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。
- 异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。
3、Spring由哪些模块组成?
以下是Spring 框架的基本模块:
- Core module(核心)
- Bean module(核心)
- Context module(核心)
- Expression Language module
- JDBC module
- ORM module
- OXM module
- Java Messaging Service(JMS) module
- Transaction module
- Web module
- Web-Servlet module
- Web-Struts module
- Web-Portlet module
4、核心容器(应用上下文) 模块。
这是基本的Spring模块,提供spring 框架的基础功能,BeanFactory 是 任何以spring为基础的应用的核心。Spring 框架建立在此模块之上,它使Spring成为一个容器。
5、 BeanFactory – BeanFactory 实现举例?
Bean 工厂是工厂模式的一个实现,提供了控制反转功能,用来把应用的配置和依赖从正真的应用代码中分离。
最常用的BeanFactory 实现是XmlBeanFactory 类。
6、Spring加载流程?
通过listener入口,核心是在AbstractApplicationContext的refresh方法,在此处进行装载bean工厂,bean,创建bean实例,拦截器,后置处理器等。
7、SpringMVC请求流程?
SpringMVC核心处理流程:
1、DispatcherServlet前端控制器接收发过来的请求,交给HandlerMapping处理器映射器
2、HandlerMapping处理器映射器,根据请求路径找到相应的HandlerAdapter处理器适配器(处理器适配器就是那些拦截器或Controller)
3、HandlerAdapter处理器适配器,处理一些功能请求,返回一个ModelAndView对象(包括模型数据、逻辑视图名)
4、ViewResolver视图解析器,先根据ModelAndView中设置的View解析具体视图
5、然后再将Model模型中的数据渲染到View上
这些过程都是以DispatcherServlet为中轴线进行的。
8、简述Spring中Bean的声明周期?
- Bean的建立, 由BeanFactory读取Bean定义文件,并生成各个实例
- Setter注入,执行Bean的属性依赖注入
- BeanNameAware的setBeanName(), 如果实现该接口,则执行其setBeanName方法
- BeanFactoryAware的setBeanFactory(),如果实现该接口,则执行其setBeanFactory方法
- BeanPostProcessor的processBeforeInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processBeforeInitialization()方法
- InitializingBean的afterPropertiesSet(),如果实现了该接口,则执行其afterPropertiesSet()方法
- Bean定义文件中定义init-method
- BeanPostProcessors的processAfterInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processAfterInitialization()方法
- DisposableBean的destroy(),在容器关闭时,如果Bean类实现了该接口,则执行它的destroy()方法
- Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法
10、使用Spring boot的好处?
- 简化编码
- 简化配置
- 简化部署
- 简化监控
11、Spring boot 加载配置顺序?
12、对Spring cloud微服务的理解?
13、讲讲 Spring 事务的传播属性?
七种传播属性。
- 事务传播行为
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:
- TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
- TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
-
事务隔离级别
隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:
-
TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
-
TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
-
TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
-
TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
-
TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
https://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/
14、Spring 如何管理事务的?
15、Spring 怎么配置事务(具体说出一些关键的 xml 元素)?
spring的声明式事务配置:
1. <!-- 配置sessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>/WEB-INF/classes/hibernate.cfg.xml</value>
</property>
</bean>
2. 配置事务管理器
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
3. 配置事务特性
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
4. 配置哪些类的哪些方法配置事务
<aop:config>
<aop:pointcut id="allManagerMethod" ession="execution(* com.yyaccp.service.impl.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod">
</aop:config>
https://www.cnblogs.com/dobestself-994395/p/4272429.html
16、说说你对 Spring 的理解,非单例注入的原理?它的生命周期?循环注入的原理, aop 的实现原理,说说 aop 中的几个术语,它们是怎么相互工作的?
单例注入是通过单例beanFactory进行创建,生命周期是在创建的时候通过接口实现开启,循环注入是通过后置处理器,aop其实就是通过反射进行动态代理,pointcut,advice等。
Aop相关:https://blog.csdn.net/weixin_38399962/article/details/79882226
17、BeanFactory和ApplicationContext有什么区别?
BeanFactory 可以理解为含有bean集合的工厂类。BeanFactory 包含了种bean的定义,以便在接收到客户端请求时将对应的bean实例化。
BeanFactory还能在实例化对象的时生成协作类之间的关系。此举将bean自身与bean客户端的配置中解放出来。BeanFactory还包含了bean生命周期的控制,调用客户端的初始化方法(initialization methods)和销毁方法(destruction methods)。
从表面上看,application context如同bean factory一样具有bean定义、bean关联关系的设置,根据请求分发bean的功能。但application context在此基础上还提供了其他的功能。
提供了支持国际化的文本消息
统一的资源文件读取方式
已在监听器中注册的bean的事件
18、你对Spring核心组件的理解?
核心组件:bean,context,core
我们知道 Bean 包装的是 Object,而 Object 必然有数据,如何给这些数据提供生存环境就是 Context 要解决的问题,对 Context 来说他就是要发现每个 Bean 之间的关系,为它们建立这种关系并且要维护好这种关系。所以 Context 就是一个 Bean 关系的集合,这个关系集合又叫 Ioc 容器,一旦建立起这个 Ioc 容器后 Spring 就可以为你工作了。那 Core 组件又有什么用武之地呢?其实 Core 就是发现、建立和维护每个 Bean 之间的关系所需要的一些列的工具,从这个角度看来,Core 这个组件叫 Util 更能让你理解。
19、简述Bean的生命周期?
Spring容器初始化-> bean构造器-> bean字段注入-> 【init-method】调用的init-method属性指定的初始化方法->容器初始化成功 ->单例bean的使用->关闭容器->【destroy-method】调用的destroy-method属性指定的初始化方法->bean死亡。
https://www.cnblogs.com/zrtqsk/p/3735273.html
20、@AspectJ 的用法?
一般@Aspect 注解的切面, 通常可以用切面表达式, 和注解切面来完成我们的切面编程.
https://blog.csdn.net/weixin_38399962/article/details/83894823
21、SpringBoot比Spring做了哪些改进?
• 独立运行
• 简化配置
• 自动配置
• 无代码生成和 XML 配置
• 应用监控
• 上手容易
详情移步: 为什么说JAVA程序员必须掌握SpringBoot?
22、你如何理解 Spring Boot 中的 Starters?
Starters 可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring 及其他技术,而不需要到处找示例代码和依赖包。如你想使用 Spring JPA 访问数据库,只要加入 spring-boot-starter-data-jpa 启动器依赖就能使用了。
Starters 包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖。
23、SpringIOC是什么?DI是什么 优点是什么?
控制反转是应用于软件工程领域中的,在运行时被装配器对象来绑定耦合对象的一种编程技巧,对象之间耦合关系在编译时通常是未知的。在传统的编程方式中,业务逻辑的流程是由应用程序中的早已被设定好关联关系的对象来决定的。在使用控制反转的情况下,业务逻辑的流程是由对象关系图来决定的,该对象关系图由装配器负责实例化,这种实现方式还可以将对象之间的关联关系的定义抽象化。而绑定的过程是通过“依赖注入”实现的。
控制反转是一种以给予应用程序中目标组件更多控制为目的设计范式,并在我们的实际工作中起到了有效的作用。
依赖注入是在编译阶段尚未知所需的功能是来自哪个的类的情况下,将其他对象所依赖的功能对象实例化的模式。这就需要一种机制用来激活相应的组件以提供特定的功能,所以依赖注入是控制反转的基础。否则如果在组件不受框架控制的情况下,框架又怎么知道要创建哪个组件?
在Java中依然注入有以下三种实现方式:
- 构造器注入
- Setter方法注入
- 接口注入
第三方中间件
1、Redis的过期删除机制?
设置过期时间,过期后的删除机制。
- 积极删除
- 立即删除
在设置键的过期时间时,创建一个回调事件,当过期时间达到时,由时间处理器自动执行键的删除操作。 - 定时删除
每隔一段时间,对expires字典进行检查,删除里面的过期键。
- 立即删除
- 消极删除
键过期了就过期了,不管。每次从dict字典中按key取值时,先检查此key是否已经过期,如果过期了就删除它,并返回nil,如果没过期,就返回键值。
2、分布式事务?
CAP定理
-
一致性(Consistency):对某个指定的客户端来说,读操作能返回最新的写操作。
-
可用性(Availability) :非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。可用性的两个关键一个是合理的时间,一个是合理的响应。
-
分区容错性(Partition tolerance): 当出现网络分区后,系统能够继续工作。打个比方,这里集群有多台机器,有台机器网络出现了问题,但是这个集群仍然可以正常工作。
分布式事务的具体方案
- 基于XA协议的两阶段提交方案.
- 第一阶段是表决阶段,所有参与者都将本事务能否成功的信息反馈发给协调者;
- 第二阶段是执行阶段,协调者根据所有参与者的反馈,通知所有参与者,步调一致地在所有分支上提交或者回滚。
两阶段提交方案应用非常广泛,几乎所有商业OLTP数据库都支持XA协议。但是两阶段提交方案锁定资源时间长,对性能影响很大,基本不适合解决微服务事务问题。
-
TCC方案
TCC方案在电商、金融领域落地较多。TCC方案其实是两阶段提交的一种改进。其将整个业务逻辑的每个分支显式的分成了Try、Confirm、Cancel三个操作。Try部分完成业务的准备工作,confirm部分完成业务的提交,cancel部分完成事务的回滚。
事务开始时,业务应用会向事务协调器注册启动事务。之后业务应用会调用所有服务的try接口,完成一阶段准备。之后事务协调器会根据try接口返回情况,决定调用confirm接口或者cancel接口。如果接口调用失败,会进行重试。
TCC方案让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量成为可能。 当然TCC方案也有不足之处,集中表现在以下两个方面:
- 对应用的侵入性强。业务逻辑的每个分支都需要实现try、confirm、cancel三个操作,应用侵入性较强,改造成本高。
- 实现难度较大。需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。为了满足一致性的要求,confirm和cancel接口必须实现幂等。
上述原因导致TCC方案大多被研发实力较强、有迫切需求的大公司所采用。微服务倡导服务的轻量化、易部署,而TCC方案中很多事务的处理逻辑需要应用自己编码实现,复杂且开发量大。
-
基于消息的最终一致性方案
消息一致性方案是通过消息中间件保证上、下游应用数据操作的一致性。基本思路是将本地操作和发送消息放在一个事务中,保证本地操作和消息发送要么两者都成功或者都失败。下游应用向消息系统订阅该消息,收到消息后执行相应操作。
消息方案从本质上讲是将分布式事务转换为两个本地事务,然后依靠下游业务的重试机制达到最终一致性。基于消息的最终一致性方案对应用侵入性也很高,应用需要进行大量业务改造,成本较高。
-
GTS–分布式事务解决方案
GTS是一款分布式事务中间件,由阿里巴巴中间件部门研发,可以为微服务架构中的分布式事务提供一站式解决方案。
3、接口鉴权?
4、Git分支管理?
- master: 主分支,主要用来版本发布。
- develop:日常开发分支,该分支正常保存了开发的最新代码。
- feature:具体的功能开发分支,只与 develop 分支交互。
- release:release 分支可以认为是 master 分支的未测试版。比如说某一期的功能全部开发完成,那么就将 develop 分支合并到 release 分支,测试没有问题并且到了发布日期就合并到 master 分支,进行发布。
- hotfix:线上 bug 修复分支。
参考:http://blog.jobbole.com/109466/
5、简单讲讲 tomcat 结构,以及其类加载器流程?
Server- –多个service
Container级别的:–>engine–》host–>context
Listenter
Connector
Logging、Naming、Session、JMX等等
6、tomcat 如何调优,涉及哪些参数?
硬件上选择,操作系统选择,版本选择,jdk选择,配置jvm参数,配置connector的线程数量,开启gzip压缩,trimSpaces,集群。
http://blog.csdn.net/lifetragedy/article/details/7708724
7、SOA和微服务的区别?
SOA是面向服务的架构,他是一种设计方法,其中包含多个服务, 服务之间通过相互依赖最终提供一系列的功能。一个服务 通常以独立的形式存在与操作系统进程中。各个服务之间 通过网络调用。
微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。
SOA和微服务理念都是服务化架构。但是侧重点不同:
区别:
- SOA
- 系统集成
- 系统的服务化
- 业务的服务化
- 微服务
- 通过服务实现组件化
- 按业务能力来划分服务和开发团队
- 去中心化
功能 | SOA | 微服务 |
---|---|---|
组件大小 | 大块业务逻辑 | 单独任务或小块业务逻辑 |
耦合 | 通常松耦合 | 总是松耦合 |
公司架构 | 任何类型 | 小型、专注于功能交叉团队 |
管理 | 着重中央管理 | 着重分散管理 |
目标 | 确保应用能够交互操作 | 执行新功能、快速拓展开发团队 |
8、Redis线程模型?
- redis是基于内存的,内存的读写速度非常快;
- redis是单线程的,省去了很多上下文切换线程的时间;
- redis使用多路复用技术,可以处理并发的连接。非阻塞IO 内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间。
9、Activate和Kafka的区别,Queue和Topic的区别?
Queue和Topic对比
类型 | Topic | Queue |
---|---|---|
概要 | Publish Subscribe messaging 发布订阅消息 | Point-to-Point 点对点 |
有无状态 | topic数据默认不落地,是无状态的。 | Queue数据默认会在mq服务器上以文件形式保存,比如Active MQ一般保存在$AMQ_HOME\data\kr-store\data下面。也可以配置成DB存储。 |
完整性保障 | 并不保证publisher发布的每条数据,Subscriber都能接受到。 | Queue保证每条数据都能被receiver接收。 |
消息是否会丢失 | 一般来说publisher发布消息到某一个topic时,只有正在监听该topic地址的sub能够接收到消息;如果没有sub在监听,该topic就丢失了。 | Sender发送消息到目标Queue,receiver可以异步接收这个Queue上的消息。Queue上的消息如果暂时没有receiver来取,也不会丢失。 |
消息发布接收策略 | 一对多的消息发布接收策略,监听同一个topic地址的多个sub都能收到publisher发送的消息。Sub接收完通知mq服务器 | 一对一的消息发布接收策略,一个sender发送的消息,只能有一个receiver接收。receiver接收完后,通知mq服务器已接收,mq服务器对queue里的消息采取删除或其他操作。 |
10、Kafka集群如何防止消息的朝哪个服消费的原理?
11、Lock和Synchronized区别以及底层实现?
Lock底层实现是利用AQS来实现的,它的基本思想就是一个同步器,支持获取锁和释放锁两个操作。
synchronized底层用的是monitor监视器来实现,monitorenter,monitorexit获取锁和释放锁。
区别
- synchronized
优点:实现简单,语义清晰,便于JVM堆栈跟踪,加锁解锁过程由JVM自动控制,提供了多种优化方案,使用更广泛
缺点:悲观的排他锁,不能进行高级功能
- lock
优点:可定时的、可轮询的与可中断的锁获取操作,提供了读写锁、公平锁和非公平锁
缺点:需手动释放锁unlock,不适合JVM进行堆栈跟踪
- synchronized是非公平锁先到先得,lock利用AQS实现是公平锁,用了CAS原理。
相同点
都是可重入锁
12、讲讲AQS?
同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成为一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态。
AQS类底层的数据结构是使用双向链表,是队列的一种实现。包括一个head节点和一个tail节点,分别表示头结点和尾节点,其中头结点不存储Thread,仅保存next结点的引用。
当一个线程成功地获取了同步状态(或者锁),其他线程将无法获取到同步状态,转而被构造成为节点并加入到同步队列中,而这个加入队列的过程必须要保证线程安全,因此同步器提供了一个基于CAS的设置尾节点的方法:compareAndSetTail(Node expect,Nodeupdate),它需要传递当前线程“认为”的尾节点和当前节点,只有设置成功后,当前节点才正式与之前的尾节点建立关联。
同步队列遵循FIFO,首节点是获取同步状态成功的节点,首节点的线程在释放同步状态时,将会唤醒后继节点,而后继节点将会在获取同步状态成功时将自己设置为首节点。
设置首节点是通过获取同步状态成功的线程来完成的,由于只有一个线程能够成功获取到同步状态,因此设置头节点的方法并不需要使用CAS来保证,它只需要将首节点设置成为原首节点的后继节点并断开原首节点的next引用即可。
13、n长度的数组,打印出里面重复的数字?
14、n个长度的数组,将奇数放在前面偶数放在后面。
思路:利用队列来实现
- 对数组遍历一次,将奇数和偶数分别放在两个队列中。
- 将奇数队列的尾结点的next指向偶数队列的头结点。即可完成。
15、Nginx的session如何处理?
-
利用Nginx自带的ip_hash,根据用户ip自动分配到对应的服务器,保证会话不丢失。使用upstream配置
优点:最简单,不用任何变动,只要改变下nginx.conf 的配置即可实现。
缺点:在重启服务后,等于将后台变成单例,那部分用户的会话还是会丢失,不能实现高可用;
如果用户ip比较集中,访问也会集中到一台服务器,那么负载均衡就失去意义。
-
利用Redis、memcached等缓存数据库实现会话的缓存。
优点:
-
性能高,可以实现高并发,大数据的系统支持;
-
水平扩展较容易,性能也不会降低。
缺点:引入第三方模块,增加架构复杂性,甚至需要修改源代码。
-
-
利用Tomcat集群自带的session共享模块。
优点:配置简单,不需要引入第三方模块,不用调整现有架构和代码。
缺点:不适合大规模集群架构,水平扩展存在性能瓶颈。
16、断路器是如何实现的?
断路器的实现采用状态机模式 。
断路器概念很简单。它用跟踪故障的监视器包装了一个函数。断路器有3种不同的状态:关闭,打开和半打开:
-
关闭 - 当一切正常时,断路器保持闭合状态,所有调用都能访问到服务。当故障数超过预定阈值时,断路器跳闸,并进入打开状态。
-
打开 - 断路器在不执行该服务的情况下为调用返回错误。
-
半开 - 超时后,断路器切换到半开状态,以测试问题是否仍然存在。如果在这种半开状态下单个调用失败,则断路器再次打开。如果成功,则断路器重置回正常关闭状态。
数据库
1、SQL语句执行顺序?
- from
- on
- join
- where
- group by
- having
- select
- distinct
- union
- order by
更多推荐
所有评论(0)