java中级面试题

1、Spring的AOP是用什么原理实现的?我回答动态代理,他说还有一个,不知道是什么?

Spring AOP是依赖JDK动态代理和CGLIB代理实现的。

在Spring中,有接口时将采用JDK的方式实现proxy代理对象,当没有接口时,将采用cglib中的方式实现prixy代理对象。

    JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。
   
     CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。

CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。   

1、JDK方式:PersonService为接口,PersonServiceBean为实现类

[java]  view plain  copy
  1.   public class JDKProxyFactory implements InvocationHandler {  
  2.    private Object targetObject;  
  3.      
  4.    public Object createProxyIntance(Object targetObject)  
  5.    {  
  6.     this.targetObject=targetObject;  
  7.     return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),   
  8.       this.targetObject.getClass().getInterfaces(), this);  
  9.    }  
  10.   
  11. public Object invoke(Object proxy, Method method, Object[] args)  
  12.   throws Throwable {  
  13.     PersonServiceBean person=(PersonServiceBean)this.targetObject;  
  14.     Object result=null;  
  15.      if(person.getUser()!=null)  
  16.      {   
  17.       result = method.invoke(targetObject, args);  
  18.       }  
  19.    return result;  
  20. }  
  21. }  

2、使用CGlib包实现:PersonServiceBean为实现类,   而没有PersonService接口

[java]  view plain  copy
  1. public class CGlibProxyFactory implements MethodInterceptor{  
  2.   private Object targetObject;  
  3.     
  4.   public Object createProxyInstance(Object targetObject)  
  5.   {   
  6.    this.targetObject=targetObject;  
  7.    Enhancer enhancer=new Enhancer();  
  8.    enhancer.setSuperclass(this.targetObject.getClass());//设置目标类的子类,该子类会覆盖所有父类中的非final方法  
  9.    enhancer.setCallback(this);//设置回调  
  10.   return  enhancer.create();  
  11.   }  
  12.   
  13. public Object intercept(Object proxy, Method method, Object[] args,  
  14.   MethodProxy methodProxy) throws Throwable {  
  15.   PersonServiceBean person=(PersonServiceBean)this.targetObject;  
  16.     Object result=null;  
  17.      if(person.getUser()!=null)  
  18.      {   
  19.       result = methodProxy.invoke(targetObject, args);  
  20.       }  
  21.  return null;  
  22. }  
  23. }  

2、JVM的工作原理?注意不是工作流程,这谁都知道

JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境. 
1.创建JVM装载环境和配置 
2.装载JVM.dll 
3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例 

4.调用JNIEnv实例装载并处理class类。

3. HashMap数据结构、扩展策略,Hash冲突攻击如何防范,如何实现线程安全的HashMap?

 JDK7以前:数组里面存linkedList,hash冲突,升级到JDK8。

JDK8,数组里面加集合,如果对象hashCode相同,不可比较时就是linkedList,可比较就会用TreeSet进行排序处理(红黑树先访问小的)。hash冲突不用防范。如果对象不可比较且hash冲突,我们可适当实现可比较接口。


线程安全:ConcurrentHashMap(系统自带的线程安全的HashMap),Map<Object, Object> synchronizedMap = Collections.synchronizedMap(new HashMap<>()); synchronizedMap 为线程安全的Map.

4. mySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据

    相关知识:redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略(回收策略)。redis 提供 6种数据淘汰策略

  • volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  • volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  • volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  • allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
  • allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  • no-enviction(驱逐):禁止驱逐数据

  5.请用Redis和任意语言实现一段恶意登录保护的代码,限制1小时内每用户Id最多只能登录5次。具体登录函数或功能用空函数即可,不用详细写出。 

    用列表实现:列表中每个元素代表登陆时间,只要最后的第5次登陆时间和现在时间差不超过1小时就禁止登陆.用Python写的代码如下:

    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3
import  redis  
import  sys  
import  time  
 
r = redis.StrictRedis(host=’ 127.0 . 0.1 ′, port= 6379 , db= 0 )  
try :       
     id = sys.argv[ 1 ]
except:      
     print(‘input argument error’)    
     sys.exit( 0 )  
if  r.llen(id) >=  5  and time.time() –  float (r.lindex(id,  4 )) <=  3600 :      
     print(“you are forbidden logining”)
else :       
     print(‘you are allowed to login’)    
     r.lpush(id, time.time())    
     # login_func()

  6.为什么redis需要把所有数据放到内存中? 

   Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。

   如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。


7.redis持久化的几种方式

1、快照(snapshots)
  缺省情况情况下,Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb。你可以配置Redis的持久化策略,例如数据集中每N秒钟有超过M次更新,就将数据写入磁盘;或者你可以手工调用命令SAVE或BGSAVE。
  工作原理
  . Redis forks.
  . 子进程开始将数据写到临时RDB文件中。
  . 当子进程完成写RDB文件,用新文件替换老文件。
  . 这种方式可以使Redis使用copy-on-write技术。
2、AOF
  快照模式并不十分健壮,当系统停止,或者无意中Redis被kill掉,最后写入Redis的数据就会丢失。这对某些应用也许不是大问题,但对于要求高可靠性的应用来说,
  Redis就不是一个合适的选择。
  Append-only文件模式是另一种选择。
  你可以在配置文件中打开AOF模式
3、虚拟内存方式
  当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大.
  当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value.
  vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的.可能会造成比较长时间的延迟,但是对数据完整性有很好的保证.

  自己测试的时候发现用虚拟内存性能也不错。如果数据量很大,可以考虑分布式或者其他数据库






  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值