Java常见题面试总结

java面试题整理!

CMS与G1?

CMS包括四个过程:初始标记 并发标记 重新标记 并发清除(步骤一和三stop the word)

CMS收集器:一款以获取最短回收停顿时间为目标的收集器,是基于“标记-清除”算法实现的

G1收集器:面向服务端应用的垃圾收集器,过程:初始标记;并发标记;最终标记;筛选回收。整体上看是“标记-整理”,局部看是“复制”,不会产生内存碎片。

 

Spring容器?

Sping的容器可以分为两种类型

1. BeanFactory:(org.springframework.beans.factory.BeanFactory接口定义)是最简答的容器,提供了基本的DI支持。最常用的BeanFactory实现就是XmlBeanFactory类,它根据XML文件中的定义加载beans,该容器从XML文件读取配置元数据并用它去创建一个完全配置的系统或应用。

2. ApplicationContext应用上下文:(org.springframework.context.ApplicationContext)基于BeanFactory之上构建,并提供面向应用的服务。

 

ApplicationContext的实现?

ClassPathXmlApplicationContext:从类路径下的XML配置文件中加载上下文定义,把应用上下文定义文件当做类资源。

FileSystemXmlApplicationContext:读取文件系统下的XML配置文件并加载上下文定义。

XmlWebApplicationContext:读取Web应用下的XML配置文件并装载上下文定义。

 

 

什么是类加载器?

负责读取Java字节代码,并转换成java.lang.Class类的一个实例

 

类加载器种类?

启动类加载器 Bootstrap ClassLoader  JAVA_HOME/lib

扩展类加载器 Extension ClassLoader  JAVA_HOME/lib/ext

应用程序类加载器 Application ClassLoader ClassPath库

自定义类加载器  通过继承ClassLoader实现,一般是加载自定义的类

 

类加载的过程?

 

加载

根据一个类的全限定名(如cn.edu.hdu.test.HelloWorld.class)来读取此类的二进制字节流到JVM内部;将字节流所代表的静态存储结构转换为方法区的运行时数据结构(hotspot选择将Class对象存储在方法区中,Java虚拟机规范并没有明确要求一定要存储在方法区或堆区中)转换为一个与目标类型对应的java.lang.Class对象;

连接(包括验证 准备 解析)

验证

验证阶段主要包括四个检验过程:文件格式验证、元数据验证、字节码验证和符号引用验证;

准备

为类中的所有静态变量分配内存空间,并为其设置一个初始值(由于还没有产生对象,实例变量将不再此操作范围内);

解析

将常量池中所有的符号引用转为直接引用(得到类或者字段、方法在内存中的指针或者偏移量,以便直接调用该方法)。这个阶段可以在初始化之后再执行。

初始化

  在连接的准备阶段,类变量已赋过一次系统要求的初始值,而在初始化阶段,则是根据程序员自己写的逻辑去初始化类变量和其他资源

 

Java多线程实现的三种方式?

继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的

 

Redis的高并发和快的原因?

redis是基于内存的,内存的读写速度非常快;

2.redis是单线程的,省去了很多上下文切换线程的时间;

3.redis使用多路复用技术,可以处理并发的连接。非阻塞IO 内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间。这里“多路”指的是多个socke网络连接,“复用”指的是复用同一个线程

 

 

MySQL limit offset?

mysql查询时,offset过大影响性能的原因是多次通过主键索引访问数据块的I/O操作

 

消息队列的应用场景?

解耦   最终一致性   广播   错峰和流控

 

乐观锁和悲观锁?

悲观锁:共享资源每次只给一个线程适用,其他线程阻塞synchronized和ReentrantLock

乐观锁:版本号和CAS算法,适用于多读的场景,可以提高吞吐量juc.atomic的实现方式

乐观锁适用于写比较少的情况,即冲突真的很少发生,省去了锁的开销,加大了系统的吞吐量。多写的情况,经常会产生冲突,导致上层不断重试,反而降低了性能,所以一般多写的情况下用悲观锁比较合适

 

ThreadPoolExecutor线程池?

SynchronousQueue LinkedBlockingQueue ArrayBlockingQueue DelayQueue

当超过最大的线程数时,且队列已满,就会跑出异常

new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());

这种线程池内部没有核心线程,线程的数量是有没限制的。

在创建任务时,若有空闲的线程时则复用空闲的线程,若没有则新建线程。

没有工作的线程(闲置状态)在超过了60S还不做事,就会销毁。

new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

该线程池的最大线程数等于核心线程数,所以在默认情况下,该线程池的线程不会因为闲置状态超时而被销毁。

如果当前线程数小于核心线程数,并且也有闲置线程的时候提交了任务,这时也不会去复用之前的闲置线程,会创建新的线程去执行任务。如果当前执行任务数大于了核心线程数,大于的部分就会进入队列等待。等着有闲置的线程来执行这个任务。

ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));

有且仅有一个工作线程执行任务

所有任务按照指定顺序执行,即遵循队列的入队出队规则

new ScheduledThreadPoolExecutor(corePoolSize);

不仅设置了核心线程数,最大线程数也是Integer.MAX_VALUE。

这个线程池是上述4个中为唯一个有延迟执行和周期执行任务的线程池。

 

防止一条数据更新两次?

触发器 唯一索引

分布式锁的三种实现方式?

数据库排他锁

某个属性唯一性约束 for update 行锁

基于ZooKeeper的分布式锁

每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。判断是否获取锁的方式很简单,只需要判断有序阶段中序号最小的一个。当释放锁的时候,只需将这个瞬时节点删除即可。

基于Redis的分布式锁

Set(key,value,nxxxmexpx,time)第一个参数是锁;第二个参数加锁的请求;第三个参数是NX,set if not exist,key存在不做操作,不存在时set操作;第四个是PX,设置过期时间

 

Redis如何保证数据一致性?

方案一:写库前后都进行redis.del(key),并且设置合理的超时时间。

方案二:异步更新缓存:MySql binlog增量订阅消费+消息队列+增量数据更新到redis

Redis哈希槽?

Redis集群有16384(2^14)个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。


使用过Redis做异步队列么,你是怎么用的?有什么缺点?

一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。缺点:在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。

 

什么是缓存穿透?如何避免?什么是缓存雪崩?如何避免?

缓存穿透

一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

如何避免?

1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。

2:对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。

缓存雪崩

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。

如何避免?

1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

2:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期

3:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

Redis适用场景?

会话缓存 全页缓存  队列(list&set) 排行榜/计数器(set/sorted set)

Redis三种架构模式?

主从复制  哨兵模式  集群模式

Redis分布式锁实现?

先用setnx来争抢锁,抢到之后,再用expire给锁添加一个过期时间防止锁忘记释放

RPC框架

 

 

Object类的九大方法?

clone(): 创建并返回此对象的一个副本

equals(): 表示某个其他对象是否与此对象“相等”

Finalize(): 当垃圾回收期确定不存在对该对象的更多引用时,由对象垃圾回收器调用方法

getClass(): 返回一个对象的运行时类

hashCode(): 返回该对象的哈希码值

Notify(): 唤醒在此对象监控器上等待的单个线程

notigyAll(): 唤醒在此对象监视器上等待的所有线程

toString():  返回该对象的字符串表示

Wait(): 导致当前的线程等待,直到其他线程调用该对象的notify()方法或者notifyAll()

 

java的wait()和notify()等方法必须在同步方法中?

每个对象都有一个“监视器monitor”,包括独占锁、入口队列、等待队列

调用wait()就是释放锁,释放锁的前提是必须要先获取锁;调用notify()方法是唤醒wait()方法的线程,让其继续执行下去

 

Wait()和sleep()的区别?

Sleep()方法是Thread类的静态方法,不涉及线程间同步概念,该过程包含了同步锁的获取和释放,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify()方法才会重新激活调用者。
注意:线程调用notify()之后,只有该线程完全从 synchronized代码里面执行完毕后,monitor才会被释放,被唤醒线程才可以真正得到执行权。

 

单例模式??

静态内部类的方式:

Public class Singleton{  

private static class SingletonHolder{ public static Singleton instance = new Singleton(); } private Singleton(){}

Public static Singleton newInstance{ return SingletonHolder.instance; }

}

 

负载均衡策略:

随机   轮询   最少活跃调用数  一致性Hash

 

 

 

 

Kafka如何保证消息不丢失和不重复?

消息丢失是什么造成的,从生产端和消费端两个角度来考虑;消息重复是什么造成的,从生产端和消费端两个角度来考虑;如何保证消息有序;如果保证消息不重不漏,损失的是什么

消费端重复消费:很容易解决,建立去重表

消费端丢失数据:也容易解决,关闭自动提交offset,处理完之后受到移位

生产端重复发送:这个不重要,消费端消费之前从去重表中判重就可以

生产端丢失数据:这个是最麻烦的情况

解决策略:

1.异步方式缓冲区满了,就阻塞在那,等着缓冲区可用,不能清空缓冲区

2.发送消息之后回调函数,发送成功就发送下一条,发送失败就记在日志中,等着定时脚本来扫描

 

 Spring的bean初始化?

调用 BeanNameAware 的 setBeanName 方法

调用 BeanFactoryAware 的 setBeanFactory 方法

调用 ApplicationContextAware 的 setApplicationContext

调用 InitializingBean 的 afterPropertiesSet 或者没有实现这个接口,但指定了@Bean(initMethod="不加括号的方法名"),会执行这个方法

调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法

调用 BeanPostProcessor 的 postProcessAfterInitialization 方法

Bean 初始化完成,可以被使用

容器关闭前,调用 DisposableBean 的 destroy 方法

 

树的广度遍历

快排

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值