面试常常问道


1.简单阐述ThreadLocaly原理

       答:ThreadLocal是通过下面的方式来实现为每一个线程维护变量的副本的:

  在ThreadLocal类中定义了一个ThreadLocalMap,每一个Thread都有一个ThreadLocalMap类型的变量threadLocals,就是用threadLocals来存储每一个线程的变量副本,threadLocals内部有一个Entry数组,我们根据键值线程对象,来找到对应线程的变量副本。

2.synchronized和lock的区别。 
   答:synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
lock:需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。
二、synchronized和lock用途区别
synchronized原语和ReentrantLock在一般情况下没有什么区别,但是在非常复杂的同步应用中,请考虑使用ReentrantLock,特别是遇到下面2种需求的时候。
1.某个线程在等待一个锁的控制权的这段时间需要中断
2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程
3.具有公平锁功能,每个到来的线程都将排队等候

3.synchronized和ReentrantLock的区别

      答:

可重入性:

从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也是可重入的,两者关于这个的区别不大。两者都是同一个线程没进入一次,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。

锁的实现:

Synchronized是依赖于JVM实现的,而ReenTrantLock是JDK实现的,有什么区别,说白了就类似于操作系统来控制实现和用户自己敲代码实现的区别。前者的实现是比较难见到的,后者有直接的源码可供阅读。

性能的区别:

在Synchronized优化以前,synchronized的性能是比ReenTrantLock差很多的,但是自从Synchronized引入了偏向锁,轻量级锁(自旋锁)后,两者的性能就差不多了,在两种方法都可用的情况下,官方甚至建议使用synchronized,其实synchronized的优化我感觉就借鉴了ReenTrantLock中的CAS技术。都是试图在用户态就把加锁问题解决,避免进入内核态的线程阻塞。

功能区别:

便利性:很明显Synchronized的使用比较方便简洁,并且由编译器去保证锁的加锁和释放,而ReenTrantLock需要手工声明来加锁和释放锁,为了避免忘记手工释放锁造成死锁,所以最好在finally中声明释放锁。

锁的细粒度和灵活度:很明显ReenTrantLock优于Synchronized

ReenTrantLock独有的能力:

1.      ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。

2.      ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。

3.      ReenTrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。

ReenTrantLock实现的原理:

在网上看到相关的源码分析,本来这块应该是本文的核心,但是感觉比较复杂就不一一详解了,简单来说,ReenTrantLock的实现是一种自旋锁,通过循环调用CAS操作来实现加锁。它的性能比较好也是因为避免了使线程进入内核态的阻塞状态。想尽办法避免线程进入内核的阻塞状态是我们去分析和理解锁设计的关键钥匙。

4  Spring AOP的概念

面向切面的编程,是一种编程技术,是OOP(面向对象编程)的补充和完善。OOP的执行是一种从上往下的流程,并没有从左到右的关系。因此在OOP编程中,会有大量的重复代码。而AOP则是将这些与业务无关的重复代码抽取出来,然后再嵌入到业务代码当中。常见的应用有:权限管理、日志、事务管理等。

实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。Spring AOP实现用的是动态代理的方式。

http://blog.csdn.net/moreevan/article/details/11977115

5  AOP的相关概念

  • 切面/方面(Aspect:AOP核心就是切面,它将多个类的通用行为封装成可重用的模块,该模块含有一组API提供横切功能。如,一个日志模块可以被称作日志的AOP切面。根据需求的不同,一个应用程序可以有若干切面。在SpringAOP中,切面通过带有@Aspect注解的类实现。
  • 连接点(Joinpoint:程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
  • 通知/增强(Advice:在切入点上,可以应用的增强包括:around、before和throws。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice:BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice。
  • 切入点(Pointcut:将被增强(Advice)应用的连接点的集合(通常是Method集合)。Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解,MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上。
  • 目标对象(TargetObject:被通知(Advice)或被代理对象。
  • AOP代理(AOP Proxy:AOP框架创建的对象,包含通知(Advice)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

6  Spring AOP的增强/通知(Advice)类型

  1. Before Advice在方法执行前执行。
  2. AfterAdvice在方法执行之后调用的通知,无论方法执行是否成功。
  3. After ReturningAdvice在方法执行后返回一个结果后执行。
  4. After ThrowingAdvice在方法执行过程中抛出异常的时候执行。
  5. Around Advice在方法执行前后和抛出异常时执行,相当于综合了以上三种通知。(相关接口MethodIntercept
  6. IntroductionAdvice引入增强):引入通知是一种特殊的通知,它能将新的成员变量、成员方法引入到目标类中。它不能作用于任何切入点,因为它只作用于类层次,而不是方法层次。实现引入通知需要实现IntroductionAdvisor和IntroductionInterceptor接口。

http://chenjumin.iteye.com/blog/364948

7  Spring AOP 的关注点和横切关注的区别

  • 关注点是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能。
  • 横切关注点是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如日志,安全和数据传输,几乎应用的每个模块都需要的功能。因此这些都属于横切关注点。

http://blog.csdn.net/shendl/article/details/526362

8  引入(Introduction)的概念

引入(Introduction:添加方法或字段到被通知的类。Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现IsModified接口,来简化缓存。Spring中要使用Introduction,可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口。

9  Spring有几种自动代理器

代理器有三类

  • 基于Bean的名字的自动代理创建器,例如BeanNameAutoProxyCreator
  • 基于Advisor(切面)匹配机制的自动代理创建器。对spring容器中的所有的Advisor扫描,并将其应用到匹配的Bean中。例如DefaultAdvisorAutoProxyCreator
  • 基于Bean中的AspjectJ注解标签的自动代理创建器,例如AnnotationAwareAspectJAutoProxyCreator

所有的自动代理创建器,都是实现了BeanPostProcessor。spring容器在实例化Bean时,BeanPostProcessor会对其加工,对满足匹配规则的Bean自动创建代理对象。

http://blog.csdn.net/itomge/article/details/8861268

http://uule.iteye.com/blog/894055

10  Spring织入概念

织入(Weaving):把切面(Aspect)应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:

  1. 编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器。
  2. 类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码。
  3. 运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了动态代理技术。

11  Spring AOP的实现方式

1、经典的基于代理的AOP:使用Java代码实现,编写Advice、PointCut,然后提供给Advisor使用。开启自动代理后,即可在applicationContext中获得增强后的bean。

http://blog.sina.com.cn/s/blog_5198c7370100hw1p.html

2、@AspectJ注解驱动的切面:基于注解的开发(推荐使用),在项目中需要开启AOP自动代理<aop:aspectj-autoproxy/>

3、XML Schema方式:需要实现相应的增强接口,如BeforeAdvice、AfterAdvice等。然后利用一下配置如:

[html] view plain copy
  1. <aop:config>    
  2.     <aop:aspect id="aspect" ref="xmlHandler">    
  3.         <aop:pointcut id="pointUserMgr" expression="execution(* com.tgb.aop.*.find*(..))"/>    
  4.             
  5.         <aop:before method="doBefore"  pointcut-ref="pointUserMgr"/>    
  6.         <aop:after method="doAfter"  pointcut-ref="pointUserMgr"/>    
  7.         <aop:around method="doAround"  pointcut-ref="pointUserMgr"/>    
  8.         <aop:after-returning method="doReturn"  pointcut-ref="pointUserMgr"/>    
  9.         <aop:after-throwing method="doThrowing" throwing="ex" pointcut-ref="pointUserMgr"/>    
  10.             
  11.     </aop:aspect>    
  12. </aop:config>   

http://blog.csdn.net/xiaoxian8023/article/details/17258933

12.常见的gc算法



     

引用计数法 Reference Counting

给对象添加一个引用计数器,每过一个引用计数器值就+1,少一个引用就-1。当它的引用变为0时,该对象就不能再被使用。它的实现简单,但是不能解决互相循环引用的问题。

根搜索算法 GC Roots Tracing

以一系列叫“GC Roots”的对象为起点开始向下搜索,走过的路径称为引用链(Reference Chain),当一个对象没有和任何引用链相连时,证明此对象是不可用的,用图论的说法是不可达的。那么它就会被判定为是可回收的对象。

JAVA里可作为GC Roots的对象
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中的类静态属性引用的对象
方法区中的常量引用的对象
本地方法栈中JNI(即Native方法)的引用的对象

标记-清除算法 Mark-Sweep

这是一个非常基本的GC算法,它是现代GC算法的思想基础,分为标记和清除两个阶段:先把所有活动的对象标记出来,然后把没有被标记的对象统一清除掉。但是它有两个问题,一是效率问题,两个过程的效率都不高。二是空间问题,清除之后会产生大量不连续的内存。

复制算法 Copying

复制算法是将原有的内存空间分成两块,每次只使用其中的一块。在GC时,将正在使用的内存块中的存活对象复制到未使用的那一块中,然后清除正在使用的内存块中的所有对象,并交换两块内存的角色,完成一次垃圾回收。它比标记-清除算法要高效,但不适用于存活对象较多的内存,因为复制的时候会有较多的时间消耗。它的致命缺点是会有一半的内存浪费

标记整理算法 Mark-Compact

标记整理算法适用于存活对象较多的场合,它的标记阶段和标记-清除算法中的一样。整理阶段是将所有存活的对象压缩到内存的一端,之后清理边界外所有的空间。它的效率也不高。

13. mysql存储引擎有哪些

(1):MyISAM存储引擎:不支持事务、也不支持外键,优势是访问速度快,对事务完整性没有 要求或者以select,insert为主的应用基本上可以用这个引擎来创建表

支持3种不同的存储格式,分别是:静态表;动态表;压缩表

静态表:表中的字段都是非变长字段,这样每个记录都是固定长度的,优点存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多(因为存储时会按照列的宽度定义补足空格)ps:在取数据的时候,默认会把字段后面的空格去掉,如果不注意会把数据本身带的空格也会忽略。

动态表:记录不是固定长度的,这样存储的优点是占用的空间相对较少;缺点:频繁的更新、删除数据容易产生碎片,需要定期执行OPTIMIZE TABLE或者myisamchk-r命令来改善性能

压缩表:因为每个记录是被单独压缩的,所以只有非常小的访问开支

(2)InnoDB存储引擎*

该存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比MyISAM引擎,写的处理效率会差一些,并且会占用更多的磁盘空间以保留数据和索引。
InnoDB存储引擎的特点:支持自动增长列,支持外键约束

(3):MEMORY存储引擎

Memory存储引擎使用存在于内存中的内容来创建表。每个memory表只实际对应一个磁盘文件,格式是.frm。memory类型的表访问非常的快,因为它的数据是放在内存中的,并且默认使用HASH索引,但是一旦服务关闭,表中的数据就会丢失掉。
MEMORY存储引擎的表可以选择使用BTREE索引或者HASH索引,两种不同类型的索引有其不同的使用范围

Hash索引优点:
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
Hash索引缺点: 那么不精确查找呢,也很明显,因为hash算法是基于等值计算的,所以对于“like”等范围查找hash索引无效,不支持;

Memory类型的存储引擎主要用于哪些内容变化不频繁的代码表,或者作为统计操作的中间结果表,便于高效地对中间结果进行分析并得到最终的统计结果,。对存储引擎为memory的表进行更新操作要谨慎,因为数据并没有实际写入到磁盘中,所以一定要对下次重新启动服务后如何获得这些修改后的数据有所考虑。

(4)MERGE存储引擎

Merge存储引擎是一组MyISAM表的组合,这些MyISAM表必须结构完全相同,merge表本身并没有数据,对merge类型的表可以进行查询,更新,删除操作,这些操作实际上是对内部的MyISAM表进行的。



猜你喜欢

转载自blog.csdn.net/u012197505/article/details/79451602