面试准备

1、Spring @Resouce 和 @Autowired 对比?

二者都是用于bean的注入
区别有:①@Autowired是spring提供的注解,而@Resouce是由J2EE提供的,在javax.annotation.Resource包html

②@Autowired默认按类型装配,若是要按照名称装配,须要加上@Qualifier注解,以下:java

public class TestServiceImpl {
    @Autowired
    @Qualifier("userDao")
    private UserDao userDao; 
}

@Resource默认经过反射机制,按照名称装配,若是匹配不上则会抛出异常。也可指定type属性进行匹配,经过类型匹配到多个或者匹配不上也会抛出异常redis

2、Redis

Redis是一个基于内存的高性能的key-value数据库算法

优势:spring

(1)速度快,应该数据都在内存中sql

(2)支持丰富的数据类型,有string、list、set、sorted set、hash数据库

(3)支持事务,操做都是原子性编程

(4)可设置过时时间,可用于缓存等设计模式

一、缓存雪崩:因为原有缓存失效(或者数据未加载到缓存中),新缓存未到期间,全部本来应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存形成巨大压力,严重的会形成数据库宕机,形成系统的崩溃。数组

 

解决思路:

  • 第一,大多数系统设计者考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,避免缓存失效时对数据库形成太大的压力,虽然可以在必定的程度上缓解了数据库的压力可是与此同时又下降了系统的吞吐量。
  • 第二,分析用户的行为,尽可能让缓存失效的时间均匀分布。
  • 第三,若是是由于某台缓存服务器宕机,能够考虑作主备,好比:redis主备,可是双缓存涉及到更新事务的问题,update可能读到脏数据,须要好好解决。

二、缓存穿透:指用户查询数据,在数据库没有,天然在缓存中也不会有。这样就致使用户查询的时候,在缓存中找不到,每次都要去数据库中查询。

解决思路:

  • 1,若是查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最简单粗暴。
  • 2,根据缓存数据Key的规则。例如咱们公司是作机顶盒的,缓存数据以Mac为Key,Mac是有规则,若是不符合规则就过滤掉,这样能够过滤一部分查询。在作缓存规划的时候,Key有必定规则的话,能够采起这种办法。这种办法只能缓解一部分的压力,过滤和系统无关的查询,可是没法根治。
  • 3,采用布隆过滤器,将全部可能存在的数据哈希到一个足够大的BitSet中,不存在的数据将会被拦截掉,从而避免了对底层存储系统的查询压力。关于布隆过滤器,详情查看:基于BitSet的布隆过滤器(Bloom Filter)

三、缓存预热:指系统上线后,将相关的缓存数据直接加载到缓存系统。这样就能够避免在用户请求的时候,先查询数据库,而后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

  • 一、直接写个缓存刷新页面,上线时手工操做下;
  • 二、数据量不大,能够在项目启动的时候自动进行加载;
  • 三、定时刷新缓存;

四、缓存更新

  • (1)定时去清理过时的缓存;
  • (2)当有用户请求过来时,再判断这个请求所用到的缓存是否过时,过时的话就去底层系统获得新数据并更新缓存。

五、缓存降级:当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然须要保证服务仍是可用的,即便是有损服务。系统能够根据一些关键数据进行自动降级,也能够配置开关实现人工降级。

  • (1)通常:好比有些服务偶尔由于网络抖动或者服务正在上线而超时,能够自动降级;
  • (2)警告:有些服务在一段时间内成功率有波动(如在95~100%之间),能够自动降级或人工降级,并发送告警;
  • (3)错误:好比可用率低于90%,或者数据库链接池被打爆了,或者访问量忽然猛增到系统能承受的最大阀值,此时能够根据状况自动降级或者人工降级;
  • (4)严重错误:好比由于特殊缘由数据错误了,此时须要紧急人工降级。

分布式缓存系统面临的问题缓存一致性问题

  • 1:缓存系统与底层数据的一致性。这点在底层系统是“可读可写”时,写得尤其重要
  • 2:有继承关系的缓存之间的一致性。为了尽可能提升缓存命中率,缓存也是分层:全局缓存,二级缓存。他们是存在继承关系的。全局缓存能够有二级缓存来组成。
  • 3:多个缓存副本之间的一致性。为了保证系统的高可用性,缓存系统背后每每会接两套存储系统(如memcache,redis等)

缓存数据的淘汰

  • (1) 定时去清理过时的缓存。
  • (2)当有用户请求过来时,再判断这个请求所用到的缓存是否过时,过时的话就去底层系统获得新数据并更新缓存。

缓存算法

  • FIFO算法:First in First out,先进先出。原则:一个数据最早进入缓存中,则应该最先淘汰掉。也就是说,当缓存满的时候,应当把最早进入缓存的数据给淘汰掉。
  • LFU算法:Least Frequently Used,最不常用算法。
  • LRU算法:Least Recently Used,近期最少使用算法。请查看:Memcached之你真正理解LRU吗(4)
  • LRU和LFU的区别。LFU算法是根据在一段时间里数据项被使用的次数选择出最少使用的数据项,即根据使用次数的差别来决定。而LRU是根据使用时间的差别来决定的

3、多线程

ThreadLocal   保证一个线程使用同一个对象

ThreadPoolExcutor  线程池建立

4、序列化和反序列化

序列化是指把对象转换为字节序列的过程;而反序列化是指把字节序列恢复为对象的过程;

序列化主要的两种用途:

1)把对象的字节序列保存到硬盘中(一般存放在一个文件中)

2)在网络上传送对象的字节序列

何时使用序列化:

1)对象序列化能够实现分布式对象,主要应用例如:RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时同样。

2)java对象序列化不只保留一个对象的数据,并且递归保存对象引用的每一个对象的数据。能够将整个对象层次写入字节流中,能够保存在文件中或在网络链接上传递。利用对象序列化能够进行对象的“深复制”,即复制对象自己及引用的对象自己。序列化一个对象可能获得整个对象序列。

5、简要描述下Spring的IoC和AOP

IoC就是对象的建立,依赖都有Spring及配置文件控制;而AOP就是统一的给一些相似的方法加上一样的功能,好比日志,事务。

IOC:控制反转,是一种设计模式。

1)控制反转,由传统在程序中控制,变为由容器控制

2)依赖注入:将互相依赖的对象分离,在Spring配置文件中描述他们的依赖关系。他们依赖关系只在使用的时候才创建。

AOP:面向切面。将系统中非核心的业务提取出来,进行单独处理,好比事务、日志和安全等。

实现方式:

  1. 注解
  2. xml配置

通知类型:

  • @Before:在目标方法被调用以前作加强处理,@Before只须要指定切入点表达式便可;
  • @AfterReturning:在目标方法正常完成后作加强,@AfterReturning除了指定切入点表达式后,还能够指定一个返回值形参名returning,表明目标方法的返回值;
  • @AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还能够指定一个throwing的返回值形参名,能够经过该形参名来访问目标方法中所抛出的异常对象;@
  • @After:在目标方法完成以后作加强,不管目标方法是否成功完成
  • @Around:环绕通知,在目标方法完成先后作加强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,

注意编程中核心是一个ProceedingJoinPoint

 1 @Component
 2 @Aspect 3 public class Operator { 4 5 @Pointcut("execution(* com.aijava.springcode.service..*.*(..))") 6 public void pointCut(){} 7 8 @Before("pointCut()") 9 public void doBefore(JoinPoint joinPoint){ 10 System.out.println("AOP Before Advice..."); 11  } 12 13 @After("pointCut()") 14 public void doAfter(JoinPoint joinPoint){ 15 System.out.println("AOP After Advice..."); 16  } 17 18 @AfterReturning(pointcut="pointCut()",returning="returnVal") 19 public void afterReturn(JoinPoint joinPoint,Object returnVal){ 20 System.out.println("AOP AfterReturning Advice:" + returnVal); 21  } 22 23 @AfterThrowing(pointcut="pointCut()",throwing="error") 24 public void afterThrowing(JoinPoint joinPoint,Throwable error){ 25 System.out.println("AOP AfterThrowing Advice..." + error); 26 System.out.println("AfterThrowing..."); 27  } 28 29 @Around("pointCut()") 30 public void around(ProceedingJoinPoint pjp){ 31 System.out.println("AOP Aronud before..."); 32 try { 33  pjp.proceed(); 34 } catch (Throwable e) { 35  e.printStackTrace(); 36  } 37 System.out.println("AOP Aronud after..."); 38  } 39 40 }

通知执行的优先级

进入目标方法时,先织入Around,再织入Before,退出目标方法时,先织入Around,再织入AfterReturning,最后才织入After。

注意:Spring AOP的环绕通知会影响到AfterThrowing通知的运行,不要同时使用!同时使用也没啥意义。

原文:https://blog.csdn.net/chinacr07/article/details/78817449 

6、说一下转发(forward)和重定向(redirect)的区别

  转发(forward)
重定向(redirect)
地址栏 不变 改成重定向的地址
数据共享 能够共享转发前request的数据 不能共享request的数据
运用 通常用于用户登陆后转发到相应模块 通常用于用户注销后回到首页和跳转到其余网站等
效率

 

 

 

 

 

7、java虚拟机内存的堆、栈、方法区

堆:线程共享,存放数组和实例化对象(GC主要在这里进行垃圾回收)jdk8后把运行时常量池、静态变量也移到堆区进行存储

虚拟机栈:线程私有,随线程建立而建立,存放基本数据类型变量和引用等(操做数栈、方法出口等信息)

本地方法栈:线程私有,与虚拟机用到native方法相关,(JNI)

方法区:常量池

程序计数器:JVM支持多个线程同时运行,每一个线程都有本身的程序计数器,运行JVM方法会保存当前指令的地址。(PS:线程执行过程当中并非一口气完成的,执行到一半中止后,下次继续执行时,经过程序计数器就能够知道该从什么地方开始执行)

8、HashMap和HashTable

 

HashMap HashTable
非线程安全 线程安全
键值容许为null 不容许为null
containsValue/containsKey contains
继承自Dictionary类 是Map接口的实现

9、cookie和session 的区别有哪些?

cookie session
数据存放在客户端 数据存放在服务器
经过http协议实现的           -
不安全(存放在浏览器) 相对安全
            - 可能影响服务器性能
常规信息可放在cookie 重要信息如登陆信息等,放在session

 10、事务的实现方式

(1)编程式事务管理。咱们须要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
(2)基于xml配置, 声明式事务管理(TransactionProxyFactoryBean)
(3)基于注解, @Transactional 的声明式事务管理
(4)基于Aspectj AOP配置事务

11、java 调用静态方法和构造函数和静态块执行的前后顺序

 1 public class ExA {  
 2     static {  
 3         System.out.println("父类--静态代码块");  
 4     }  
 5    
 6     public ExA() {  
 7         System.out.println("父类--构造函数");  
 8     }  
 9    
10     {  
11         System.out.println("父类--非静态代码块");  
12     }  
13    
14     public static void main(String[] args) {  
15         new ExB();  
16     }  
17 }  
18    
19 class ExB extends ExA {  
20     static {  
21         System.out.println("子类--静态代码块");  
22     }  
23     {  
24         System.out.println("子类--非静态代码块");  
25     }  
26    
27     public ExB() {  
28         System.out.println("子类--构造函数");  
29     }  
30 }  
31  
32 执行结果 
33 ===== 
34 父类--静态代码块 
35 子类--静态代码块 
36 父类--非静态代码块 
37 父类--构造函数 
38 子类--非静态代码块 
39 子类--构造函数

12、java中的sleep()和wait()的区别

sleep()是Thread类中的方法,而wait是Object类提供的方法;

调用sleep()方法的时候,线程不会释放对象锁;

调用wait()方法的时候,线程会释放对象锁,只有对此对象调用notify()方法后,才获取对象锁进入运行状态

原文:https://www.cnblogs.com/hongten/p/hongten_java_sleep_wait.html

十3、sql优化 

(一)、索引

如下状况不会命中索引:

  1. 使用 !=或<>
  2. 使用 is nul / is not null (解决方案:设置默认值,好比设置默认0)
  3. 使用 or ( 解决方案:使用union all链接两次查询结果)
  4. 使用 like %xxxx
  5. 使用 in / not in (解决方案:使用between 或者 exist)
  6. 使用 自定义参数 @xxx (解决方案:强制使用索引,如:select id from t with(index(索引名)) where num=@num)
  7. 使用 函数,如:select id from t where substring(name,1,3)='abc'  /   select id from t where datediff(day,createdate,'2005-11-30')=0
  8. 使用 数学运算 如:select id from t where num/2=100
  9. 若是该索引是复合索引,那么必须使用到该索引中的第一个字段做为条件时才能保证系统使用该索引,不然该索引将不会被使用,而且应尽量的让字段顺序与索引顺序相一致。
相关文章
相关标签/搜索