java面试题

Servlet运行原理以及生命周期 http://www.cnblogs.com/fifiyong/p/6390805.html
mysql db cpu过高的情况
跨域原理及解决办法
session 与 cookie
@RequestParam和@RequestBody的区别

Redis、MongoDB及Memcached的区别

理解java类加载器以及ClassLoader类

组合索引的使用

JVM调优总结 -Xms -Xmx -Xmn -Xss

mybatis 加载原理 底层实现 一级缓存和二级缓存
springboot 和springmvc比较的优势
springcloud 相关组件介绍

Redis数据过期策略详解

线上服务CPU100%问题快速定位实战

什么是springboot
用来简化spring应用的初始搭建以及开发过程 使用特定的方式来进行配置(properties或yml文件)
创建独立的spring引用程序 main方法运行
嵌入的Tomcat 无需部署war文件
简化maven配置
自动配置spring添加对应功能starter自动化配置
springboot常用的starter有哪些
spring-boot-starter-web 嵌入tomcat和web开发需要servlet与jsp支持
spring-boot-starter-data-jpa 数据库支持
spring-boot-starter-data-redis redis数据库支持
spring-boot-starter-data-solr solr支持
mybatis-spring-boot-starter 第三方的mybatis集成starter
springboot自动配置的原理
在spring程序main方法中 添加@SpringBootApplication或者@EnableAutoConfiguration会自动去maven中读取每个starter中的spring.factories文件 该文件里配置了所有需要被创建spring容器中的bean

springboot读取配置文件的方式
springboot默认读取配置文件为application.properties或者是application.yml
springboot集成mybatis的过程
添加mybatis的starter maven依赖
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.2.0
在mybatis的接口中 添加@Mapper注解
在application.yml配置数据源信息
springboot如何添加【修改代码】自动重启功能
添加开发者工具集=====spring-boot-devtools
什么是微服务
以前的模式是所有的代码在同一个工程中部署在同一个服务器中同一个项目的不同模块不同功能互相抢占资源
微服务将工程根据不同的业务规则拆分成微服务 微服务部署在不同的机器上 服务之间进行相互调用Java微服务的框架有 dubbo(只能用来做微服务),spring cloud(提供了服务的发现,断路器等)
springcloud如何实现服务的注册和发现
服务在发布时 指定对应的服务名(服务名包括了IP地址和端口) 将服务注册到注册中心(eureka或者zookeeper)这一过程是springcloud自动实现 只需要在main方法添加@EnableDisscoveryClient 同一个服务修改端口就可以启动多个实例
调用方法:传递服务名称通过注册中心获取所有的可用实例 通过负载均衡策略调用(ribbon和feign)对应的服务

ribbon和feign区别
Ribbon添加maven依赖 spring-starter-ribbon 使用@RibbonClient(value="服务名称") 使用RestTemplate调用远程服务对应的方法
feign添加maven依赖 spring-starter-feign 服务提供方提供对外接口 调用方使用 在接口上使用@FeignClient("指定服务名")
Ribbon和Feign的区别:
Ribbon和Feign都是用于调用其他服务的,不过方式不同。
1.启动类使用的注解不同,Ribbon用的是个@RibbonClient,Feign用的是@EnableFeignClients。
2.服务的指定位置不同,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口中使用@FeignClient声明。
3.调用方式不同,Ribbon需要自己构建http请求,模拟http请求然后使用RestTemplate发送给其他服务,步骤相当繁琐。
Feign则是在Ribbon的基础上进行了一次改进,采用接口的方式,将需要调用的其他服务的方法定义成抽象方法即可,不需要自己构建http请求。不过要注意的是抽象方法的注解、方法签名要和提供服务的方法完全一致。
springcloud断路器的作用
当一个服务调用另一个服务由于网络原因或者自身原因出现问题时 调用者就会等待被调用者的响应 当更多的服务请求到这些资源时导致更多的请求等待 这样就会发生连锁效应(雪崩效应) 断路器就是解决这一问题断路器有完全打开状态一定时间内 达到一定的次数无法调用 并且多次检测没有恢复的迹象 断路器完全打开,那么下次请求就不会请求到该服务半开短时间内 有恢复迹象 断路器会将部分请求发给该服务 当能正常调用时 断路器关闭 关闭当服务一直处于正常状态 能正常调用 断路器关闭

实现短连接算法
500万用户文件,包含userid,age字段,一个2亿的用户记录文件, 先按年龄段过滤并且按用户记录排序

查询各课程的平均成绩并按成绩降序排列
select 科目 ,avg(成绩) from 课程
group by 科目
order by agv(成绩)
一、语句为:
SELECT S.学号,姓名,AVG(成绩)平均成绩 FROM S,SC
WHERE S.学号=SC.学号
GROUP BY S.学号 HAVING COUNT(*)>5 ORDER BY 3 DESC

二、注意要点:
1)题目要求查询平均成绩,表中不存在“平均成绩”字段,需要使用VAG函数。
2)学生表student和成绩表score都含有“学号”字段,在查询时需指明学号属于哪个表。
3)GROUP BY短语对于查询结果进行分组,后跟随HAVING短语来限定分组必须满足查询选修课在5门以上的学生,必须在分组后再统计,所以CONM(大)>S应在HAVING后。



分库分表策略,常见的策略有
取模(库ID 按主键 或hash字符串主键 % 库数量 表ID 主键或hash字符串主键/库数量%表数量)、分区(可按照时间分区、范围分区,时间分区规则如一个月一个表、一年一个库。范围分区规则如0~2000万一个表,2000~4000万一个表。如果分区规则很复杂,则可以有一个路由表来存储分库分表规则。分区的缺点是存在热点,但是易于水平扩展,能避免数据迁移。)、路由表等。

synchronized与Lock的区别
类别
synchronized
Lock
存在层次
Java的关键字,在jvm层面上
是一个类
锁的释放
1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁
在finally中必须释放锁,不然容易造成线程死锁
锁的获取
假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待
分情况而定,Lock有多个锁获取的方式,具体下面会说道,大致就是可以尝试获得锁,线程可以不用一直等待
锁状态
无法判断
可以判断
锁类型
可重入 不可中断 非公平
可重入 可判断 可公平(两者皆可)
性能
少量同步
大量同步

为什么使用B+树?言简意赅,就是因为:
1.文件很大,不可能全部存储在内存中,故要存储到磁盘上
2.索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数(为什么使用B-/+Tree,还跟磁盘存取原理有关。)
3.局部性原理与磁盘预读,预读的长度一般为页(page)的整倍数,(在许多操作系统中,页得大小通常为4k)
4. 数据库系统巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样 每个节点只需要一次I/O 就可以完全载入,(由于节点中有两个数组,所以地址连续)。而红黑树这种结构,h明显要深的多。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性

数据库连接池有很多实现,如C3P0、DBCP、Druid等。
工厂模式一般分为3种:简单工厂、工厂、抽象工厂。
一、三种工厂的实现是越来越复杂的
二、简单工厂通过构造时传入的标识来生产产品,不同产品都在同一个工厂中生产,这种判断会随着产品的增加而增加,给扩展和维护带来麻烦
三、工厂模式无法解决产品族和产品等级结构的问题
四、抽象工厂模式中,一个工厂生产多个产品,它们是一个产品族,不同的产品族的产品派生于不同的抽象产品(或产品接口)。
1、在上面的代码中,都使用了接口来表达抽象工厂或者抽象产品,那么可以用抽象类吗?有何区别?
从功能上说,完全可以,甚至可以用接口来定义行为,用抽象类来抽象属性。抽象类更加偏向于属性的抽象,而用接口更加偏向行为的规范与统一。使用接口有更好的可扩展性和可维护性,更加灵活实现松散耦合,所以编程原则中有一条是针对接口编程而不是针对类编程。
2. 到底何时应该用工厂模式
根据具体业务需求。不要认为简单工厂是用switch case就觉得一无是处,也不要觉得抽象工厂比较高大上就到处套。我们使用设计模式是为了解决问题而不是炫技,所以根据三种工厂模式的特质,以及对未来扩展的预期,来确定使用哪种工厂模式。
3.说说你在项目中工厂模式的应用
如果你看了这篇文章,被问到这个问题时,还傻乎乎的去举数据库连接的例子,是要被打板子的。。。比如我之前做过一个旅游产品的B2B网站,根据不同类型的业务形态,产品也是不同的,有国内跟团,出境跟团,国内自由行,出境自由行,邮轮五种产品,并且后面可能还会有门票,酒店,机票等等产品,其中有些联系也有些区别。
所以在面试中,我完全把工厂模式和我做的东西联系起来,如何建立工厂,如何生产不同的产品,如何扩展,如何维护等等。我想,把理论应用到实际,而且是真实业务逻辑中,给面试官的印象无论如何不会太差,甚至会对你刮目相看。
当然,即便是你没有真的使用过,如果面试官问道了工厂模式,你仍然可以把你以往的经验和设计模式联系起来回(hu)答(you)面试官,只要你理解了,把来龙去脉说清楚,并且可以回答问题,我想应该是可以令面试官满意的。
代理模式:
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.

订单失效处理方案:
1、 https://github.com/ouqiang/delay-queue
2、 延迟队列
rabbitmq-delayed-message-exchange
延迟队列让您可以将队列中新消息的传递操作推迟指定的毫秒数
byte[] messageBodyBytes = "delayed payload" .getBytes( "UTF-8" ) ; Map headers = new HashMap() ; headers.put( "x-delay" , 5000 ) ; AMQP. BasicProperties.Builder props = new AMQP. BasicProperties.Builder().headers(headers); channel. basicPublish("my-exchange", "" , props. build(), messageBodyBytes) ;
如上会将消息推迟 5000 毫秒才会推送给消费者.
优点:1、 消息传输可靠 2、延迟小 3、开源免费 4、高可用
同一张表同样的SQL 一个走索引,一个不走
select count(id) from st_alldata_m m left join a_stbprp where paratype='0001'
paraid 有索引 ,
如果条件是 paratype=‘0001’ 不走索引;
条件是 paratype=‘0004’ 就走索引;
求指教啊
paratype 没有空值

可能是优化器在查询'0001'值时,判断 全表扫描 快于索引,要看你的索引选择度是否高
也可能是该表经常增删改,产生过多索引碎片,导致索引失效
前一种就是系统合理判断(也有可能是统计信息采集出错),
后一种需要重建或重组索引


CGLib方式对接口实现代理
JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
简单的实现举例:
这是一个需要被代理的类,也就是父类,通过字节码技术创建这个类的子类,实现动态代理。
public class SayHello {
public void say(){
System.out.println("hello everyone");
}
}
该类实现了创建子类的方法与代理的方法。getProxy(SuperClass.class)方法通过入参即父类的字节码,通过扩展父类的class来创建代理对象。intercept()方法拦截所有目标类方法的调用,obj表示目标类的实例,method为目标类方法的反射对象,args为方法的动态入参,proxy为代理类实例。proxy.invokeSuper(obj, args)通过代理类调用父类中的方法。
public class CglibProxy implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
//实现MethodInterceptor接口方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
//通过代理类调用父类中的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置代理");
return result;
}
}
具体实现类:
public class DoCGLib {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
//通过生成子类的方式创建代理类
SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
proxyImp.say();
}
}
输出结果:
前置代理
hello everyone
后置代理
JDK动态代理的原理是根据定义好的规则,用传入的接口创建一个新类,这就是为什么采用动态代理时为什么只能用接口引用指向代理,而不能用传入的类引用执行动态类。
CGLib采用的是用创建一个继承实现类的子类,用asm库动态修改子类的代码来实现的,所以可以用传入的类引用执行代理类
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理


Integer a = 1 Integer b = 1 a==b -> true Integer a = 1111 Integer b = 1111 a==b -> false 求解释啊。
在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,因为是重用,所以 Integer b = 1,实际上并没有重新生成对象,而是引用了Integer a对象
实际上参考的是同一个对象。 内存地址 一样,所以结果是true,如果你是这样写
Integer a= new Integer(1);
Integer b = new Integer(1);
那么结果就会是false了,应该他确实重新生成对象了
如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,
即相当于每次装箱时都新建一个 Integer对象,所以Integer a = 1111 Integer b = 1111参考的是不同的对象。 内存地址 不同,结果是false,对象如果要比较值,应该用.equals()方法



java语言支持的变量类型
类变量:独立于方法之外的变量,用 static 修饰。
局部变量:类的方法中的变量。
实例变量(全局变量):独立于方法之外的变量,不过没有 static 修饰。
实例变量非线程安全
ArrayList和LinkedList的大致区别如下:
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
分布式锁同时去创建顺序子节点并watch 拥有最小序号的持有锁 当释放锁,所有人被通知,再次检测自己是否是最小

水平分表:每个字表的字段都一样,目的:解决单表容量不足(1000w);垂直分表:每个字表的字段不一样,目的:避免单表单行太大,引起分页存储。用uuid做主键,由于不是业务相关,分库分表(散列 连续)需要业务主键做路由。
spring starter的工作原理 springboot在启动时扫描所依赖的jar包,寻找包含spring.factories文件的jar包根据spring.factories配置加载AutoConfigure类根据@Conditional注解的条件,进行自动配置并将Bean注入Spring Context。
zk和eureka区别:zk主要是保证数据一致性,eureka保证可用性。eureka还提供了自我保护等机制。
spring如何解决循环依赖的?
rocketmq消费者发生异常怎么办?消息是如何落地的?
nignx负载均衡策略有哪些?
spring容器初始化过程是怎样的?
线程池的参数最大线程数是做什么的,如果超过了会有什么问题?
mybatis的#和$有什么区别?
将一个链表排序

有一个生成唯一串的需求,并发请求量非常大,该如何实现?
ip+进程号+当前时间(精确到纳秒)+计数器(每次批量生成串的时候重置计数器为0),由定时检查队列的线程批量生成后放到队列(可以采用LinkedBlockingQueue )中,一秒种检查一次队列中的串数量,队列大小可以设置为指定的数量,当队列中的串数量低于多少时,往队列中追加新生成的串。获取串的线程访问由队列控制即可。
思路:
1、生成串由单线程批量生成。
2、并发获取的线程由队列(队列采用链表的阻塞队列实现)进行控制。
串的生成格式:ip+进程号+当前时间(精确到纳秒)+计数器(每次批量生成串的时候重置计数器为0)
可以解决,多机多JVM实例的问题,计数器可以解决时间相同的问题

spring 加载过程 注解
springmvc加载过程 注解 参数区别
servlet是不是线程安全的 在什么场景下安全 什么场景下不安全
redis nginx 线程模型
mycat分库分表处理
volital 使用场景
OOM错误,stackoverflow错误,permgen space错误
如果线程请求的栈的深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。
一个对象jvm过程
触发JVM进行Full GC的情况及应对策略
1、System.gc()方法的调用
此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full GC的频率,也即增加了间歇性停顿的次数。强烈影响系建议能不使用此方法就别使用,让虚拟机自己去管理它的内存,可通过通过-XX:+ DisableExplicitGC来禁止RMI调用System.gc。
2、老年代代空间不足
老年代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行Full GC后空间仍然不足,则抛出如下错误:
java.lang.OutOfMemoryError: Java heap space
为避免以上两种状况引起的Full GC,调优时应尽量做到让对象在Minor GC阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。
3、永生区空间不足
JVM规范中运行时数据区域中的方法区,在HotSpot虚拟机中又被习惯称为永生代或者永生区,Permanet Generation中存放的为一些class的信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下也会执行Full GC。如果经过Full GC仍然回收不了,那么JVM会抛出如下错误信息:
java.lang.OutOfMemoryError: PermGen space
为避免Perm Gen占满造成Full GC现象,可采用的方法为增大Perm Gen空间或转为使用CMS GC。
4、CMS GC时出现promotion failed和concurrent mode failure
对于采用CMS进行老年代GC的程序而言,尤其要注意GC日志中是否有promotion failed和concurrent mode failure两种状况,当这两种状况出现时可能
会触发Full GC。promotion failed是在进行Minor GC时,survivor space放不下、对象只能放入老年代,而此时老年代也放不下造成的;concurrent mode failure是在
执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足造成的(有时候“空间不足”是CMS GC时当前的浮动垃圾过多导致暂时性的空间不足触发Full GC)。
对措施为:增大survivor space、老年代空间或调低触发并发GC的比率,但在JDK 5.0+、6.0+的版本中有可能会由于JDK的bug29导致CMS在remark完毕
后很久才触发sweeping动作。对于这种状况,可通过设置-XX: CMSMaxAbortablePrecleanTime=5(单位为ms)来避免。
5、统计得到的Minor GC晋升到旧生代的平均大小大于老年代的剩余空间
这是一个较为复杂的触发情况,Hotspot为了避免由于新生代对象晋升到旧生代导致旧生代空间不足的现象,在进行Minor GC时,做了一个判断,如果之
前统计所得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间,那么就直接触发Full GC。
例如程序第一次触发Minor GC后,有6MB的对象晋升到旧生代,那么当下一次Minor GC发生时,首先检查旧生代的剩余空间是否大于6MB,如果小于6MB,
则执行Full GC。
当新生代采用PS GC时,方式稍有不同,PS GC是在Minor GC后也会检查,例如上面的例子中第一次Minor GC后,PS GC会检查此时旧生代的剩余空间是否
大于6MB,如小于,则触发对旧生代的回收。
除了以上4种状况外,对于使用RMI来进行RPC或管理的Sun JDK应用而言,默认情况下会一小时执行一次Full GC。可通过在启动时通过- java -
Dsun.rmi.dgc.client.gcInterval=3600000来设置Full GC执行的间隔时间或通过-XX:+ DisableExplicitGC来禁止RMI调用System.gc。
6、堆中分配很大的对象
所谓大对象,是指需要大量连续内存空间的java对象,例如很长的数组,此种对象会直接进入老年代,而老年代虽然有很大的剩余空间,但是无法找到足够大的连续空间来分配给当前对象,此种情况就会触发JVM进行Full GC。
为了解决这个问题,CMS垃圾收集器提供了一个可配置的参数,即-XX:+UseCMSCompactAtFullCollection开关参数,用于在“享受”完Full GC服务之后额外免费赠送一个碎片整理的过程,内存整理的过程无法并发的,空间碎片问题没有了,但提顿时间不得不变长了,JVM设计者们还提供了另外一个参数 -XX:CMSFullGCsBeforeCompaction,这个参数用于设置在执行多少次不压缩的Full GC后,跟着来一次带压缩的。
方法区和栈都存放的什么
AtomicInteger的API 及其Unsafe 实现了什么
G1收集器 CMS收集器
CMS收集器是基于“标记-清楚”算法实现的,整个过程分为4个步骤,包括:
初始标记(CMS initial mark)
并发标记(CMS concurrent mark)
重新标记(CMS remark)
并发清除(CMS concurrent sweep)
其中初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以总体来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。
优点:并发收集、低停顿
缺点:CMS收集器对CPU资源非常敏感
CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。
内存碎片
G1收集器

空间分配担保
在发生Minor GC之前,虚拟机会先检查老年代最大可以的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC可以确保是安全的。
wait notify 写生产者和消费者模式
dubbo 协议 dubbo支持的并发量 使用场景
HashMap、ArrayList、HashSet等的关系和区别
数据结构和算法
常见的排序算法就不说了,需要理解其原理和会写代码,还有时间空间复杂度也要知道
队列、栈:需要理解其存取结构,并能在某些场景下使用
二叉树:树的遍历、树的深度、按层次输出、平衡二叉树、逆序打印树等
链表:逆序、合并两有序的链表、判断链表是否又环、链表倒数第K个元素等
字符串:KMP算法、动态规划(这个是重点,需要好好理解动态规划,常见的题有:求解最长回文子串、求解最长公共子串等)
海量数据处理:现在好多大公司都会问海量数据的处理,所以需要掌握常见的处理方法,比如Bit-map、分而治之、hash映射等,可以百度看看相关的文章,加深理解
sonr 代码检查工具
阿里书写规范检查
arrayList 的扩容

线程私有的内存:程序计数器 、java虚拟机栈
程序计数器是一块较小的内存区域。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储。
虚拟机栈描述的是java方法执行的内存模型。

1 、CMS收集器
CMS收集器是一种以获取最短回收停顿时间为目标的收集器。基于“标记-清除”算法实现,它的运作过程如下:
1)初始标记
2)并发标记
3)重新标记
4)并发清除
初始标记、从新标记这两个步骤仍然需要“stop the world”,初始标记仅仅只是标记一下GC Roots能直接关联到的对象,熟读很快,并发标记阶段就是进行GC Roots Tracing,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生表动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长点,但远比并发标记的时间短。
java面试题_第1张图片
CMS是一款优秀的收集器,主要优点:并发收集、低停顿。
缺点:
1)CMS收集器对CPU资源非常敏感。在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用了一部分线程而导致应用程序变慢,总吞吐量会降低。
2)CMS收集器无法处理浮动垃圾,可能会出现“Concurrent Mode Failure(并发模式故障)”失败而导致Full GC产生。
浮动垃圾:由于CMS并发清理阶段用户线程还在运行着,伴随着程序运行自然就会有新的垃圾不断产生,这部分垃圾出现的标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC中再清理。这些垃圾就是“浮动垃圾”。
3)CMS是一款“标记--清除”算法实现的收集器,容易出现大量空间碎片。当空间碎片过多,将会给大对象分配带来很大的麻烦,往往会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC。
2 、G1收集器
G1是一款面向服务端应用的垃圾收集器。G1具备如下特点:
1、并行于并发:G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短stop-The-World停顿时间。部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行。
2、分代收集:虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但是还是保留了分代的概念。它能够采用不同的方式去处理新创建的对象和已经存活了一段时间,熬过多次GC的旧对象以获取更好的收集效果。
3、空间整合:与CMS的“标记--清理”算法不同,G1从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。
4、可预测的停顿:这是G1相对于CMS的另一个大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,
5、G1运作步骤:
1、初始标记;2、并发标记;3、最终标记;4、筛选回收
上面几个步骤的运作过程和CMS有很多相似之处。初始标记阶段仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS的值,让下一个阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这一阶段需要停顿线程,但是耗时很短,并发标记阶段是从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段时耗时较长,但可与用户程序并发执行。而最终标记阶段则是为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remenbered Set Logs里面,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set Logs里面,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中,这一阶段需要停顿线程,但是可并行执行。最后在筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。
java面试题_第2张图片


项目介绍
大部分情况,这是一场面试的开门题,面试官问这个问题,主要是考察你的概述能力和全局视野。有的人经常抱怨自己每天在堆业务,但没有成长。事实上,很多情况下确实在堆业务,但并不是没有成长的。并非做中间件或者技术架构才是成长,例如我们的需求分析能力,沟通协作能力,产品思维能力,抽象建模能力等都是一个非常重要的硬实力。
好的,现在进入正文。
1、明确项目是做什么的 2、明确项目的价值。(为什么做这个项目,它解决了用户什么痛点,它带来什么价值?) 3、明确项目的功能。(这个项目涉及哪些功能?) 4、明确项目的技术。(这个项目用到哪些技术?) 5、明确个人在项目中的位置和作用。(你在这个项目的承担角色?) 6、明确项目的整体架构。 7、明确项目的优缺点,如果重新设计你会如何设计。 8、明确项目的亮点。(这个项目有什么亮点?) 9、明确技术成长。(你通过这个项目有哪些技术成长?)
Java基础
1、List 和 Set 的区别 2、HashSet 是如何保证不重复的 3、HashMap 是线程安全的吗,为什么不是线程安全的(最好画图说明多线程环境下不安全)? 4、HashMap 的扩容过程 5、HashMap 1.7 与 1.8 的 区别,说明 1.8 做了哪些优化,如何优化的? 6、final finally finalize 7、强引用 、软引用、 弱引用、虚引用 8、Java反射 9、Arrays.sort 实现原理和 Collection 实现原理 10、LinkedHashMap的应用 11、cloneable接口实现原理 12、异常分类以及处理机制 13、wait和sleep的区别 14、数组在内存中如何分配
Java 并发
1、synchronized 的实现原理以及锁优化? 2、volatile 的实现原理? 3、Java 的信号灯? 4、synchronized 在静态方法和普通方法的区别? 5、怎么实现所有线程在等待某个事件的发生才会去执行? 6、CAS?CAS 有什么缺陷,如何解决? 7、synchronized 和 lock 有什么区别? 8、Hashtable 是怎么加锁的 ? 9、HashMap 的并发问题? 10、ConcurrenHashMap 介绍?1.8 中为什么要用红黑树? 11、AQS 12、如何检测死锁?怎么预防死锁? 13、Java 内存模型? 14、如何保证多线程下 i++ 结果正确? 15、线程池的种类,区别和使用场景? 16、分析线程池的实现原理和线程的调度过程? 17、线程池如何调优,最大数目如何确认? 18、ThreadLocal原理,用的时候需要注意什么? 19、CountDownLatch 和 CyclicBarrier 的用法,以及相互之间的差别? 20、LockSupport工具 21、Condition接口及其实现原理 22、Fork/Join框架的理解 23、分段锁的原理,锁力度减小的思考 24、八种阻塞队列以及各个阻塞队列的特性
Spring
1、BeanFactory 和 FactoryBean? 2、Spring IOC 的理解,其初始化过程? 3、BeanFactory 和 ApplicationContext? 4、Spring Bean 的生命周期,如何被管理的? 5、Spring Bean 的加载过程是怎样的? 6、如果要你实现Spring AOP,请问怎么实现? 7、如果要你实现Spring IOC,你会注意哪些问题? 8、Spring 是如何管理事务的,事务管理机制? 9、Spring 的不同事务传播行为有哪些,干什么用的? 10、Spring 中用到了那些设计模式? 11、Spring MVC 的工作原理? 12、Spring 循环注入的原理? 13、Spring AOP的理解,各个术语,他们是怎么相互工作的? 14、Spring 如何保证 Controller 并发的安全?
Netty
1、BIO、NIO和AIO
2、Netty 的各大组件
3、Netty的线程模型
4、TCP 粘包/拆包的原因及解决方法
粘包问题的解决策略
由于底层的TCP无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决。
(1)消息定长,例如每个报文的大小为固定长度200字节,如果不够,空位补空格;
(2)在包尾增加回车换行符进行分割,例如FTP协议;
(3)将消息分为消息头和消息体,消息头中包含表示消息总长度(或者消息体长度)的字段,通常设计思路为消息头的第一个字段使用int32来表示消息的总长度;
(4)更复杂的应用层协议。
5、了解哪几种序列化协议?包括使用场景和如何去选择
6、Netty的零拷贝实现
7、Netty的高性能表现在哪些方面
分布式相关
1、Dubbo的底层实现原理和机制
2、描述一个服务从发布到被消费的详细过程
3、分布式系统怎么做服务治理
4、接口的幂等性的概念
5、消息中间件如何解决消息丢失问题
6、Dubbo的服务请求失败怎么处理
Dubbo超时和重连机制
dubbo启动时默认有重试机制和超时机制。
超时机制的规则是如果在一定的时间内,provider没有返回,则认为本次调用失败,
重试机制在出现调用失败时,会再次调用。如果在配置的调用次数内都失败,则认为此次请求异常,抛出异常。
如果出现超时,通常是业务处理太慢,可在服务提供方执行:jstack PID > jstack.log 分析线程都卡在哪个方法调用上,这里就是慢的原因。
如果不能调优性能,请将timeout设大。
某些业务场景下,如果不注意配置超时和重试,可能会引起一些异常。
1.超时设置
DUBBO消费端设置超时时间需要根据业务实际情况来设定,
如果设置的时间太短,一些复杂业务需要很长时间完成,导致在设定的超时时间内无法完成正常的业务处理。
这样消费端达到超时时间,那么dubbo会进行重试机制,不合理的重试在一些特殊的业务场景下可能会引发很多问题,需要合理设置接口超时时间。
比如发送邮件,可能就会发出多份重复邮件,执行注册请求时,就会插入多条重复的注册数据。
(1)合理配置超时和重连的思路
1.对于核心的服务中心,去除dubbo超时重试机制,并重新评估设置超时时间。
2.业务处理代码必须放在服务端,客户端只做参数验证和服务调用,不涉及业务流程处理
(2)Dubbo超时和重连配置示例
2.重连机制
dubbo在调用服务不成功时,默认会重试2次。
Dubbo的路由机制,会把超时的请求路由到其他机器上,而不是本机尝试,所以 dubbo的重试机器也能一定程度的保证服务的质量。
但是如果不合理的配置重试次数,当失败时会进行重试多次,这样在某个时间点出现性能问题,调用方再连续重复调用,
系统请求变为正常值的retries倍,系统压力会大增,容易引起服务雪崩,需要根据业务情况规划好如何进行异常处理,何时进行重试。
7、重连机制会不会造成错误
8、对分布式事务的理解
9、如何实现负载均衡,有哪些算法可以实现?
轮询(Round Robin)法
随机(Random)法
源地址哈希(Hash)法
加权轮询(Weight Round Robin)法
加权随机(Weight Random)法
最小连接数(Least Connections)法
10、Zookeeper的用途,选举的原理是什么?
11、数据的垂直拆分水平拆分。
12、zookeeper原理和适用场景
13、zookeeper watch机制
14、redis/zk节点宕机如何处理
15、分布式集群下如何做到唯一序列号
16、如何做一个分布式锁
17、用过哪些MQ,怎么用的,和其他mq比较有什么优缺点,MQ的连接是线程安全的吗
18、MQ系统的数据如何保证不丢失
19、列举出你能想到的数据库分库分表策略;分库分表后,如何解决全表查询的问题
20、zookeeper的选举策略
21、全局ID
数据库
1、mysql分页有什么优化 2、悲观锁、乐观锁 3、组合索引,最左原则 4、mysql 的表锁、行锁 5、mysql 性能优化 6、mysql的索引分类:B+,hash;什么情况用什么索引 7、事务的特性和隔离级别
缓存
1、Redis用过哪些数据数据,以及Redis底层怎么实现 2、Redis缓存穿透,缓存雪崩 3、如何使用Redis来实现分布式锁 4、Redis的并发竞争问题如何解决 5、Redis持久化的几种方式,优缺点是什么,怎么实现的 6、Redis的缓存失效策略 7、Redis集群,高可用,原理 8、Redis缓存分片 9、Redis的数据淘汰策略
JVM
1、详细jvm内存模型 2、讲讲什么情况下回出现内存溢出,内存泄漏? 3、说说Java线程栈 4、JVM 年轻代到年老代的晋升过程的判断条件是什么呢? 5、JVM 出现 fullGC 很频繁,怎么去线上排查问题? 6、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式? 7、类的实例化顺序 8、JVM垃圾回收机制,何时触发MinorGC等操作 9、JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的 10、各种回收器,各自优缺点,重点CMS、G1 11、各种回收算法 12、OOM错误,stackoverflow错误,permgen space错误


public int hashCode() {
int h = hash ;
if (h == 0 && value . length > 0 ) {
char val[] = value ;

for ( int i = 0 ; i < value . length ; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}

// 在指定位置插入指定元素
public void insert(int index, String s) {
//定义新数组,长度是原数组长度+1
String[] dest = new String[src.length+1];
//将原数组的数据拷贝到新数组
System.arraycopy(src, 0, dest, 0, index);
dest[index]=s;
System.arraycopy(src, index, dest, index+1, src.length-index);
src=dest;
}

public class MyStack_Text { static class mystack { int mytop; int stack[]; public mystack( int num) { mytop=-1; stack= new int [num]; } /*出栈*/ void mypop() { mytop--; } /*入栈*/ void mypush( int x) { mytop++; stack[mytop]=x; } /*判空*/ Boolean myisempty() { if (mytop==-1) return true ; else return false ; } /*取栈顶元素*/ int mypeek() { int peek=stack[mytop]; return peek; } /*栈大小*/ int mysize() { return mytop+1; } }


一、redis事务与关系型数据库事务比较

1、操作事务命令
mysql 使用start transaction 开启事物,rollback 回滚事物,commit 提交事物。redis 使用multi 开始事物,discard 取消事物,exec 提交事物。
从场景1中可以看出mysql 开启事务后事务中的sql 语句在commit 之前就已经执行了sql 语句的,只是并未真正提交到数据库。redis 使用multi 开启事务后,编写的sql 语句都进入queue 队列中,待执行exec 提交事物时才一次性按进入queue 队列的顺序提交到数据库。同样针对回滚,mysql 执行rollback 会将提交的数据回滚,redis 因为没有提交到数据,使用discard 只是单纯取消在queue 中的sql 语句。

从场景2中可以看出,mysql 事务即使遇到错误的语句也会提交正确的sql 到数据库,需要程序员控制当遇到语句异常时进行回滚,redis 与mysql 不同,提交事务时当queue 中有语法错误语句会discard 整个事务中的sql 语句。

从场景3中可以看出,mysql 和redis 事务当遇到操作对象类型不正确的时候都会提交执行事务。

2、事务锁

在关系型数据库中主要通过乐观锁和悲观锁进行数据库事务的并发控制。而在redis 中是通过watch 加乐观锁对数据库进行并发控制。
mysql 悲观锁是通过select * from table where for update将数据加锁,导致其他线程或事务不能更新该数据。相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本。数据版本为数据增加的一个版本标识。当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新,否则认为是过期数据。
关系型数据库mysql 实现数据版本主要有两种方式,第一种是使用版本号,第二种是使用时间戳。使用版本号时,可以在数据初始化时指定一个版本号,每次对数据的更新操作都对版本号执行+1操作。并判断当前版本号是不是该数据的最新的版本号。

二、redis入门指南(三) redis的事务和回滚
redis包括INCR在内的所有Redis命令都是原子操作。redis支持简单的事务,但没有关系型数据库事务提供的回滚功能。如果事务里的一条命令出现了运行错误,事务里其他的命令依然会继续执行。
Redis的事务(部分支持)
开启事务使用MULTI,但不见得开启,redis会返回ok代表我收到了,所有命令使用EXEC调用,使用DISCARD放弃事务,表示不玩了
常用的命令有:
WATCH key(keys) 监视一个或多个key,如果在事务执行之前这个或这些key被其他命令所改动,那么事务将被打断
MULTI 标记一个事务块的开始
EXEC 执行所有事务块内的命令
DISCARD 取消事务,放弃执行事务块内的所有命令
UNWATCH 取消WATCH 命令对所有 key 的监控

三、redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作

四、线程池之拒绝策略
http://note.youdao.com/noteshare?id=ec2d4a98cdac7a8e7dc651a2315b55d1

五、Redis为什么使用单进程单线程方式也这么快
http://note.youdao.com/noteshare?id=8f2e5ea7c04ac11138c307888a043a8c
六、 那Redis服务端是使用单进程还是多进程,单线程还是多线程来处理客户端请求的呢?
答案是单进程单线程。
七、Redis和I/O多路复用
http://blog.csdn.net/tanswer_/article/details/70196139
八、mysql 事务隔离级别
https://www.cnblogs.com/huanongying/p/7021555.html
九、cms和g1收集器的原理和过程

十、synchronized 与 Lock 的那点事
https://www.cnblogs.com/benshan/p/3551987.html
十一、redis常见面试题
https://www.cnblogs.com/jiahaoJAVA/p/6244278.html
https://www.cnblogs.com/mushroom/p/4738170.html
十二、jvm
https://www.cnblogs.com/prayers/p/5515245.html
十三、java中的锁
http://www.importnew.com/19472.html
十四、markword的结构,偏向锁&轻量级锁&重量级锁
http://blog.csdn.net/xiaomin1991222/article/details/50981423
https://www.cnblogs.com/charlesblc/p/5994162.html
cas :compare and swap 比较并设置
Java对象头
锁存在Java对象头里。如果对象是数组类型,则虚拟机用3个Word(字宽)存储对象头,如果对象是非数组类型,则用2字宽存储对象头。在32位虚拟机中,一字宽等于四字节,即32bit。
Java对象头里的Mark Word里默认存储对象的HashCode,分代年龄和锁标记位。
32位JVM的Mark Word的默认存储结构如下:
Java SE1.6为了减少获得锁和释放锁所带来的性能消耗,引入了“偏向锁”和“轻量级锁”
十五、cas 缺点
CAS缺点
CAS虽然很高效的解决原子操作,但是CAS仍然存在三大问题。ABA问题,循环时间长开销大和只能保证一个共享变量的原子操作
1. ABA问题。因为CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。ABA问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么A-B-A 就会变成1A-2B-3A。
从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。
关于ABA问题参考文档: http://blog.hesey.net/2011/09/resolve-aba-by-atomicstampedreference.html
2. 循环时间长开销大。自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。如果JVM能支持处理器提供的pause指令那么效率会有一定的提升,pause指令有两个作用,第一它可以延迟流水线执行指令(de-pipeline),使CPU不会消耗过多的执行资源,延迟的时间取决于具体实现的版本,在一些处理器上延迟时间是零。第二它可以避免在退出循环的时候因内存顺序冲突(memory order violation)而引起CPU流水线被清空(CPU pipeline flush),从而提高CPU的执行效率。
3. 只能保证一个共享变量的原子操作。当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁,或者有一个取巧的办法,就是把多个共享变量合并成一个共享变量来操作。比如有两个共享变量i=2,j=a,合并一下ij=2a,然后用CAS来操作ij。从Java1.5开始JDK提供了AtomicReference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行CAS操作。
十六、加密算法
十七、双亲委派模型,用处,为何要打破双亲委派模型,自定义的java.lang.string是否能够运行?
十八、mysql数据库用过吧?里面的索引是基于什么数据结构?
索引主要基于Hash表或者B+数
十九、请你说一说B+数的实现细节是什么样?B-树和B+树有什么区别?联合索引在B+树中如何存储?
B-树就是B树,中间的横线并不是减号。
树的查询效率高,而且可以保持有序。其实从算法逻辑上来讲,二叉查找树的速度和比较次数都是最小。
但是,我们不得不考虑一个现实问题:磁盘IO。
数据库索引是存储在磁盘上的,当数据量比较大的时候,索引的大小可能有几个G甚至更多。当我们利用索引查询的时候,能把整个索引全部加载到内存吗?显然不可能。能做的只有逐一加载每一个磁盘页,这里的磁盘页对应着索引树的节点。
如果用二叉查找数作为索引:磁盘IO的次数是4次,索引数的高度也是4。所以最坏的情况下,磁盘io次数等于索引树的高度。
B数是一种多路平衡查找树,它的每一个节点最多包含K个孩子,K被称为B树的阶。K的大小取决于磁盘页的大小。
下面来具体介绍一下B-树(Balance Tree),一个m阶的B树具有如下几个特征:
1.根结点至少有两个子女。
2.每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m
3.每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m
4.所有的叶子结点都位于同一层。
5.每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划
B-树主要应用于文件系统以及部分数据库索引,比如著名的非关系型数据库MongDB。而大部分关系型数据库,比如mysql,则使用B+树作为索引。
B+树是基于B-树的一种变体,有着比B-树更高的查询性能。

一个m阶的B+树具有如下几个特征:
1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。

B+树还具有一个特点,这个特点是在索引之外,确是至关重要的特点。那就是【卫星数据】的位置。
所谓卫星数据,指的是索引元素所指向的数据记录,比如数据库中的某一行。在B-树中,无论中间节点还是叶子节点都带有卫星数据。
而在B+树中,只有叶子节点带有卫星数据,其余中间节点仅仅是索引,没有任何数据关联。
需要补充的是,在数据库的聚集索引(Clustered Index)中,叶子节点直接包含卫星数据。在非聚集索引(NonClustered Index)中,叶子节点带有指向卫星数据的指针。

综合起来,B+树相比B-数的优势有三个:1、IO次数更少;2、查询性能稳定;3、范围查询简便。

B+树的特征:
1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。

B+树的优势:
1.单一节点存储更多的元素,使得查询的IO次数更少。
2.所有查询都要查找到叶子节点,查询性能稳定。
3.所有叶子节点形成有序链表,便于范围查询。

二十、HashMap是线程安全的吗?在并发场景下,ConcurrentHashMap是怎样保证线程安全的?又是怎样实现高性能读写的?HashMap的底层数据结构(数组和链表 底层算法:hash(key))
HashMap不是线程安全的。在并发插入元素的时候,有可能出现带环链表,让下一次读操作出现死循环。
HashMap的默认初始长度是16,并且每次自动扩展或是手动初始化时,长度必须是2的幂。HashMap的发明者采用了位运算的方式。
index = HashCode(Key) & (Length - 1)
下面我们以值为“book”的Key来演示整个过程:
1.计算book的hashcode,结果为十进制的3029737,二进制的101110001110101110 1001。
2.假定HashMap长度是默认的16,计算Length-1的结果为十进制的15,二进制的1111。
3.把以上两个结果做与运算,101110001110101110 1001 & 1111 = 1001,十进制是9,所以 index=9。
可以说,Hash算法最终得到的index结果,完全取决于Key的Hashcode值的最后几位。

Rehash是HashMap在扩容时候的一个步骤
影响发生Resize的因素有两个:
1.Capacity HashMap的当前长度。
2.LoadFactor HashMap负载因子,默认值为0.75f。

衡量HashMap是否进行Resize的条件如下:
HashMap.Size >= Capacity * LoadFactor
扩容步骤:
1.扩容
创建一个新的Entry空数组,长度是原数组的2倍。
2.ReHash
遍历原Entry数组,把所有的Entry重新Hash到新数组。为什么要重新Hash呢?因为长度扩大以后,Hash的规则也随之改变。

想要避免HashMap的线程安全问题有很多办法,比如改用HashTable或者Collections.synchronizedMap,但是两者有共同的问题:性能。无论读操作还是写操作,它们都会给整个集合加锁,导致同一时间的其他操作为之阻塞。

二十一、hash冲突的解决方法以及hashMap的底层实现
一般比较常用的方法有开放地址法:(内容来自百度百科)
1. 开放寻址法:Hi=(H(key) + di) MOD m,i=1,2,…,k(k<=m-1),其中H(key)为散列函数,m为散列表长,di为增量序列,可有下列三种取法:
1.1. di=1,2,3,…,m-1,称线性探测再散列;顺序查看表的下一单元,直至找到某个空单元,或查遍全表。
1.2. di=1^2,-1^2,2^2,-2^2,⑶^2,…,±(k)^2,(k<=m/2)称二次探测再散列;在表的左右进行跳跃式探测。
1.3. di=伪随机数序列,称伪随机探测再散列。根据产生的随机数进行探测。
2 再散列法:建立多个hash函数,若是当发生hash冲突的时候,使用下一个hash函数,直到找到可以存放元素的位置。
3 拉链法(链地址法):就是在冲突的位置上简历一个链表,然后将冲突的元素插入到链表尾端,
4 建立公共溢出区:将哈希表分为基本表和溢出表,将与基本表发生冲突的元素放入溢出表中。
http://blog.csdn.net/qq_25901775/article/details/50930140

mybatis中的#和$的区别
. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id".
2. $将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.
3. #方式能够很大程度防止sql注入。 
4.$方式无法防止Sql注入。
5.$方式一般用于传入数据库对象,例如传入表名. 
6.一般能用#的就别用$.
MyBatis排序时使用order by 动态参数时需要注意,用$而不是#

二十二、实现线程同步的几种方式
http://blog.csdn.net/small_lee/article/details/51453019
1.synchronized 同步方法或者同步代码块
2、使用特殊域变量(volatile)实现线程同步
3、使用重入锁实现线程同步
4、使用局部变量实现线程同步
如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,
副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。

二十三、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表进行的。

二十四、java基础—常用的GC策略,什么时候会触发YGC,什么时候触发FGC?
一、内存回收策略和常见概念
常见内存回收策略可以从以下几个维度来理解:
1 串行&并行
串行:单线程执行内存回收工作。十分简单,无需考虑同步等问题,但耗时较长,不适合多cpu。
并行:多线程并发进行回收工作。适合多CPU,效率高。
2 并发& stop the world
stop the world:jvm里的应用线程会挂起,只有垃圾回收线程在工作进行垃圾清理工作。简单,无需考虑回收不干净等问题。
并发:在垃圾回收的同时,应用也在跑。保证应用的响应时间。会存在回收不干净需要二次回收的情况。
3 压缩&非压缩©
压缩:在进行垃圾回收后,会通过滑动,把存活对象滑动到连续的空间里,清理碎片,保证剩余的空间是连续的。
非压缩:保留碎片,不进行压缩。
copy:将存活对象移到新空间,老空间全部释放。(需要较大的内存。)
一个垃圾回收算法,可以从上面几个维度来考虑和设计,而最终产生拥有不同特性适合不同场景的垃圾回收器
二、JVM的YGC&FGC
YGC :对新生代堆进行GC。频率比较高,因为大部分对象的存活寿命较短,在新生代里被回收。性能耗费较小。
FGC :全堆范围的GC。默认堆空间使用到达80%(可调整)的时候会触发FGC。以我们生产环境为例,一般比较少会触发FGC,有时10天或一周左右会有一次。
三、什么时候会触发YGC,什么时候触发FGC?
YGC的时机:
edn空间不足
FGC的时机:
1.old空间不足;
2.perm空间不足;
3.显示调用System.gc() ,包括RMI等的定时触发;
4.YGC时的悲观策略;
5.dump live的内存信息时(jmap –dump:live)。
对YGC的 触发时机,相当的显而易见,就是eden空间不足, 这时候就肯定会触发ygc
对于FGC的触发时机, old空间不足, 和perm的空间不足, 调用system.gc()这几个都比较显而易见,就是在这种情况下, 一般都会触发GC。
最复杂的是所谓的悲观策略,它触发的机制是在首先会计算之前晋升的平均大小,也就是从新生代,通过ygc变成新生代的平均大小,然后如果旧生代剩余的空间小于晋升大小,那么就会触发一次FullGC。sdk考虑的策略是, 从平均和长远的情况来看,下次晋升空间不够的可能性非常大, 与其等到那时候在fullGC 不如悲观的认为下次肯定会触发FullGC, 直接先执行一次FullGC。而且从实际使用过程中来看, 也达到了比较稳定的效果。

二十五、TCP的流量控制
TCP使用窗口机制进行流量控制
TCP协议通过滑动窗口来实现流量的控制
什么是窗口?
连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端接收方发送的确认信息中包含了自己剩余的缓冲区尺寸
HTTP/HTTPS区别
(1)HTTPS是HTTP的安全版,是HTTP+SSL,HTTP协议以明文方式发送内容,不提供任何方式的数据加密;
(2)https协议需要到ca申请证书,一般免费证书很少,需要交费。http是免费的;
(3)http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443;
(4)http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
maven冲突如何解决 build-helper-maven-plugin

二十六、redis的五种数据结构:String字符串、List列表、Set集合、Hash散列、Zset有序集合
二十七、数据库隔离级别
读未提交(Read uncommitted) 、读已提交(Read committed)、可重复度(Repeatable read)、可串行化(Serializable)
mysql默认的事务处理级别是'REPEATABLE-READ',也就是可重复读
1.查看当前会话隔离级别
select @@tx_isolation;
2.查看系统当前隔离级别
select @@global.tx_isolation;
3.设置当前会话隔离级别
set session transaction isolatin level repeatable read;
4.设置系统当前隔离级别
set global transaction isolation level repeatable read;

java面试题_第3张图片
LRU算法:
常见序列化协议及其优缺点:
如果线上服务器频繁出现full gc,如何去排查
消息队列广播模式和发布/订阅模式的区别?

JVM的永久代中会发生垃圾回收么?
垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免Full GC是非常重要的原因。

什么情况索引不会命中,会造成全表扫描
1.不要使用in操作符,这样数据库会进行全表扫描,
2.not in 使用not in也不会走索引
3.<> 操作符(不等于) 使用<>同样不会使用索引,因此对它的处理只会产生全表扫描
4.IS NULL 或IS NOT NULL操作(判断字段是否为空)
5.> 及 < 操作符(大于或小于操作符)
6.LIKE操作符
7.UNION操作符
8.WHERE后面的条件顺序影响

当一个对象到GC ROOTS 没有任何引用链相连时,则证明此对象是不可用的。
可作为GC Roots的对象包括下面几种:
虚拟机栈(栈帧中的本地变量表)中引用的对象。
方法区中类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI(即一般说的Native方法)引用的对象。

分代收集算法
新生代 复制 老年代 标记-清理或标记-整理
大对象直接进入老年代:所谓大对象是指,需要大量连续内存空间的java对象,最典型的大对象就是那种很长的字符串以及数组。提供了一个 -XX:PretenureSizeThreshold 参数,令大于这个设置的对象直接在老年代分配。
长期存活对象将进入老年代:对象晋升老年代的年龄阈值,可以通过-XX:MaxTenuringThreshold 设置 默认是15


什么场景下可以使用 volatile 替换 synchronized

单例模式:
public class Singleton { private static volatile Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null ) { synchronized (Singleton. class ) { if (singleton == null ) { singleton = new Singleton(); } } } return singleton; }}
优点:线程安全;延迟加载;效率较高。

java中的equals hashCode的区别和联系?
他们是在Object类中定义的。 equals(Object obj)方法用来判断两个对象是否“相同”,如果“相同”则返回true,否则返回false。 hashcode()方法返回一个int数,在Object类中的默认实现是“将该对象的内部地址转换成一个整数返回”。
接下来有两个个关于这两个方法的重要规范(我只是抽取了最重要的两个,其实不止两个): 规范1:若重写equals(Object obj)方法,有必要重写hashcode()方法,确保通过equals(Object obj)方法判断结果为true的两个对象具备相等的hashcode()返回值。说得简单点就是:“如果两个对象相同,那么他们的hashcode应该 相等”。不过请注意:这个只是规范,如果你非要写一个类让equals(Object obj)返回true而hashcode()返回两个不相等的值,编译和运行都是不会报错的。不过这样违反了Java规范,程序也就埋下了BUG。 规范2:如果equals(Object obj)返回false,即两个对象“不相同”,并不要求对这两个对象调用hashcode()方法得到两个不相同的数。说的简单点就是:“如果两个对象不相同,他们的hashcode可能相同”。 根据这两个规范,可以得到如下推论: 1、如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。 2、如果两个对象不equals,他们的hashcode有可能相等。 3、如果两个对象hashcode相等,他们不一定equals。 4、如果两个对象hashcode不相等,他们一定不equals。

TheadLocal的原理及使用场景?
ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。
简述Spring AOP?
是SSH里面的一种Spring + Struts +Hibernate,如今MVC模式下的一种框架。
应对需求快速变化,主要原因有一种面向切面编程(AOP)的优势。
系统中用到的 对象不在系统加载时就全部实例化,而是在调用时才会实例化需要的
优点:
1、降低了组件之间的耦合性,实现了软件各层之间的解耦。
2、可以使用容易提供的众多服务,如:事务管理,消息服务,日志记录等。
3、容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。
AOP:面向切面编程
通过 预编译 方式和运行期动态代理实现程序功能唯一维护,
允许通过分离应用的业务逻辑与系统级服务和事务进行内聚性开发。
主要将日志记录、性能统计、安全控制、事务处理、异常处理等代码从业务逻辑代码中划分出来。
IOC:控制反转
是一个重要的面向对象编程的法则来 削减 计算机程序的 耦合问题
Spring框架的核心
应用控制反转,对象被创建的时候,由一个调控系统内所有对象的外界实体将其所以来的对象的引用传递给它。
最基本的Java技术就是“反射”编程。
引入实现IOC模式的IOC容器,可由IOC容器来管理对象的生命周期、依赖关系,从而使得应用程序的配置和依赖性规范与实际应用程序分开。(把对象生成放在XML中定义)
描述下java的Error、Exception的区别,试着举例几种RuntimeException?
Error类和Exception类的父类都是throwable类,他们的区别是:
Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。
Exception类表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。
Exception类又分为运行时异常(Runtime Exception)和受检查的异常(Checked Exception ),运行时异常;ArithmaticException,IllegalArgumentException,编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。而受检查的异常,要么用try。。。catch捕获,要么用throws字句声明抛出,交给它的父类处理,否则编译不会通过。

常见的异常;
ArrayIndexOutOfBoundsException 数组下标越界异常,
ArithmaticException 算数异常 如除数为零
NullPointerException 空指针异常
IllegalArgumentException 不合法参数异常

如何判断两个单向链表相交,如何找到相交点?
1、判断第一个链表的每个节点是否在第二个链表中
2、把第二个链表连接到第一个后面,判断得到的链表是否有环,有环则相交
3、先遍历第一个链表,记住最后一个节点,再遍历第二个链表,得到最后一个节点时和第一个链表的最后一个节点做比较,如果相同,则相交
讲解java克隆的作用以及深浅克隆的原理区别?
答案是:克隆的对象可能包含一些已经修改过的属性,而new出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠clone方法了。那么我把这个对象的临时属性一个一个的赋值给我新new的对象不也行嘛?可以是可以,但是一来麻烦不说,二来,大家通过上面的源码都发现了clone是一个native方法,就是快啊,在底层实现的。
提个醒,我们常见的Object a=new Object();Object b;b=a;这种形式的代码复制的是引用,即对象在内存中的地址,a和b对象仍然指向了同一个对象。
而通过clone方法赋值的对象跟原来的对象时同时独立存在的。

简述下TCP的三次握手?
TCP/IP协议 中, TCP协议 提供可靠的连接服务,采用三次握手建立一个连接.
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
SYN:同步序列编号(Synchronize Sequence Numbers)
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入 SYN_RECV 状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手.
完成三次握手,客户端与服务器开始传送数据
简述线程同步的几种方式?
1.同步方法 即用synchronized关键字修饰的方法。
2.同步代码块 即有synchronized关键字修饰的语句块。
3.使用特殊域变量(volatile)实现线程同步
4.使用重入锁实现线程同步 ReentrantLock类是可重入、互斥、实现了Lock接口的锁
5.使用局部变量实现线程同步 ThreadLocal
题目描述:
现有表 tb1 ,有字段 name, class, score .分别代表 姓名,所在班级,分数。
要求:用一条SQL语句查询出每个班的及格人数和不及格人数,格式为:class,及格人数,不及格人数(score>=60为及格)
select class 班级,
sum(case when score>=60 then 1 else 0 end) as 及格人数,
sum(case when score<60 then 1 else 0 end) as 不及格人数
from tb1
group by class;

nginx的error log 日志格式,统计出日志中频次最多的10个ip地址(linux shell实现)
awk '{c[$7]++}END{for(i in c) print i,c[i]}' error.log | sort -k2 -nr | head -10

根据规律填充括号内容 1,11,21,1211,111221,(312211)

test A
I am B

代码输出问题:
public class Test {
public static void main(String args[]){
A a = new B();
test (a);
}

public static void test(A a){
System. out . println ( "test A" );
a.whoAmI();
}

public static void test(B b){
System. out . println ( "test B" );
b.whoAmI();
}
}

class A{
public void whoAmI(){
System. out . println ( "I am A" );
}
}
class B extends A{
public void whoAmI(){
System. out . println ( "I am B" );
}
}



实际是先实例化一个子类对象,然后在转换为父类对象。先调用父类构造函数,再调用子类构造函数。当子类重写了父类的方法时,将调用子类的bar()方法。子类没有重写父类方法时,将调用父类方法test()。

美团网
1、两条链表,求相同的node。
java方面
java中的引用有几种?
Java中的threadlocal是怎么用的? threadlocal中的内部实现是怎么样的? 哪种引用?
java中的"final"关键字在多线程的语义中,有什么含义
说说nio的架构,为什么变快了,说说select和 buffer 都是怎么用的?
在操作系统中的实现原理? 如果都是cpu轮训话,会不会对cpu影响太大?
应用到了linux中的什么特性?
nio中, 如果不显式的调用 system.gc() 那会出现什么问题?
jvm的垃圾回收分为哪些种类?每一种都是怎么去实现的?讲述一下G1的回收策略?
jvm中的参数分为哪些种类,都是做什么的?jvm的监控怎么做?实际项目上线以后的监控怎么做?
JVM中,如果把堆内存参数配置的超过了本地内存,会怎么样?
JVM中的内存结构分为哪些方面?
栈空间是怎么样的?每个线程只有一个栈吗?
栈空间的内部结构是怎么样的?
堆内存为什么要设计为分代?
ArrayList的实现原理,如何测试ArrayList动态分配内存中带来的内存、cpu变化
ArrayList是不是线程安全的? 怎么实现线程安全的?
synchronized和lock有什么区别?
volatile的作用,如果volatile修饰的对象经过了大量的写,会出现什么问题?
String的+和StringBuilder有什么区别? 放在循环中有什么问题?
日志打印的过程中,使用String的+操作和使用占位符输出,对性能上有什么区别
SimpleDateFormat如果是一个全局变量的话,有什么问题?
HashMap的操作中,直接使用keySet()遍历有什么问题?
计算机结构方面
linux中awk命令的使用?
nginx是多线程还是单线程?
linux中如何监控和查看内存、cpu情况?
负载分为哪些类别和层次?你们项目中是怎么用的?
mq是如何使用的?
http协议建立连接的过程是怎么样的?
https建立连接的的过程是怎么样的?
forward和redirect有什么区别?
linux如何实现nginx的高性能?有什么特性被应用了?直接来说,就是基于linux的网络编程
redis中,是如何进行

数据库方面
  1. 数据流的锁级别,乐观锁和悲观锁的概念,是不是只有悲观锁?
  2. 数据库如何实现事务?
  3. 有没有什么研究深入的技术,或者比较满意的项目?

1.写树的中序非递归遍历算法&&后序非递归遍历
2.数据库索引
问了我索引的种类,特点以及怎样实现的,我提到了聚集非聚集以及B树红黑树,他详细问了红黑树,B树和二叉树区别。
聚集索引和非聚集索引
什么是回表?
简单来说就是数据库根据索引找到了指定的记录所在行后,还需要根据rowid再次到数据块里取数据的操作;
怎么避免回表?
如果只是简单的查询name id 这种情况 可以考虑创建组合索引 要根据实际情况考虑创建索引的成本!
3.单例模式
写了单线程的,多线程的
4.桥模式
解释了组合代替继承,抽象和实现分离
5.项目细节和软件编程感悟
我主要讲了自己对软件开发的看法


CMS收集器所基于的垃圾收集算法
如何查看内容很大的日志,并进行滚动 less
top里面如何看各个cpu的使用率,以及各个参数含义
按c,其实是按1
0.3% us 用户空间占用CPU百分比
1.0% sy 内核空间占用CPU百分比
0.0% ni 用户进程空间内改变过优先级的进程占用CPU百分比
98.7% id 空闲CPU百分比
0.0% wa 等待输入输出的CPU时间百分比
0.0% hi 硬中断
0.0% si 软中断

1.为什么用static,static有什么用?
2.jvm分区
3.gc算法
4.快排时间复杂度,为什么?
5.设计模式
6.算法歌曲重排名
7.两个大文件,寻找共同行
8.做过的项目
9.storm重启 数据丢失
10.redis多线程修改
11.volatile atomic

二叉树 层级遍历
二叉树深度优先
操作系统 CPU调度算法

二叉树 层级遍历二叉树深度优先数据库四大特性 隔离级别数据库三大范式操作系统 CPU调度算法计算机网络 7层协议 三次握手图的遍历KMP算法

3.面试官来了以后先让我自我介绍,我介绍完以后就说了说最近做的项目;
4.说完项目以后,面试官让我把项目架构画下来,我把架构画了一遍,然后问了我一些技术选型,架构方面的知识;
5.还问了我多线程,线程池,等等的基础问题;
6.最后他还是说我的java基础不太扎实,但是给我过了,然后就把我带到楼上进行第二轮面试;
7.第二轮面试就在他们开发人员的旁边,看到他们的工作环境,然后还是聊项目,然后聊性格,让我很差异,我都怀疑我面前的是技术面还是hr面试,哈哈,然后最后给我出了一道字符串的编程题,让我写,当时脑子太乱了,没写出来,然后面试官人特别好,说让我晚上写出来了给他发过去,然后就让我走了,说等通知,不知道是不是还有没有下文了。
面试官问的面试题:1.jvm2.多线程,线程池3.架构设计4.项目经验,遇到的问题等等5.数据结构。


1>如何定位线上服务OOM问题 
2>JVM的GC ROOTS存在于那些地方
3>mysql innodb怎样做查询优化
  4>java cas的概念
  下面静儿就以自己面试的标准简单回答一下这些题怎样回答算过关。
  1>如何定位线上服务OOM问题
  因为面试主要是看思路,答案还是其次,那么要是我回答这个问题。我可能会把整个思路都说出来:Java服务OOM,比较常见的原因是
  ⭐️ 有可能是内存分配确实过小,而正常业务使用了大量内存
    比如jmap -heap命令可以查看新生代老年代的堆内存大小及使用情况,看看是否内存本身分配过小。
  ⭐️ 某一个对象被频繁申请,却没有释放,内存不断泄漏,导致内存耗尽
    比如jmap -histo:live 对象显示存活对象的信息,并按照所占内存大小的排序。因为包含了实例数、所占内存大小、类名,所以很直观。
  ⭐️ 某一个资源被频繁申请,系统资源耗尽,例如:不断创建线程,不断发起网络连接  
    可以用pstree、netstat查看进程创建线程数,网络连接数,如果资源耗尽,也会出现OOM。也可以查看/proc/${PID}/fd 和/proc/${PID}/task,查看句柄详情和线程数。
  
  2>JVM的GC ROOTS存在于那些地方
  问到这个问题应该是前面一步步引导过来的,如果没有,在直接回答这个问题之前,最好简要描述一下JVM的内存结构和根搜索算法(GC ROOTS Tracing)做可达性分析。
  GC Roots的对象包括如下几种(静儿来新美大的时候就被我们架构师问过这个问题):
  ⭐️ 虚拟机栈(栈桢中的本地变量表)中的引用的对象
  ⭐️ 方法区中的类静态属性引用的对象
  ⭐️ 方法区中的常量引用的对象
  ⭐️ 本地方法栈中JNI的引用的对象
  GC管理的主要区域是Java堆,一般情况下只针对堆进行垃圾回收。方法区、栈和本地方法区不被GC所管理,因而选择这些区域作为GC ROOTS。被GC ROOTS引用的对象不会被垃圾回收。
  
  3>mysql innodb怎样做查询优化
  这个问题的答案就比较多了,各人的心得都是不一样的。主要考察在工作实践中的总结和思考能力。最好面试者能在总结的通用答案之后加上实际项目中的使用例子。
  ⭐️ innodb_buffer_pool_size 此参数的作用是缓冲数据和索引,对性能可以产生线性的提高,最大可设置为内存大小的百分之七八十的样子
  ⭐️ 打开慢查询日志,增加参数:log-queries-not-using-indexes,方便把系统中没有走索引的sql语句全抓出来优化
  ⭐️ 通过explain做查询分析,看看有没有用索引,访问的行数rows
  ⭐️ 关闭skip_name_resolve,减少逆向DNS解析的消耗
  另外还有一些实际写代码过程中深入骨髓的,比如数据动静分离提高query_cache的命中率啦,减少字段冗余,减少查询次数啦,复杂查询分解啦,分页优化啦啥的。
  很多人说面试题和实际开发联系不大,觉得没啥用。其实很多活培训两个月都是能干的。人和人之间的差距确实没有明显到你能干我不能干的程度。但是之前做过一个项目,我和别人一起干,干完之后我要修改很多其他人的各种慢查询问题啦,性能问题啦之类。我看了他们写的sql,我发现这些sql我会理所当然不那么用的。因为我在人人的时候就很注意这些方面,我认为是理所当然的,知道这样影响性能。
  还有就是面试评价好的人实际写代码的时候确实出的问题要少,因为他们考虑更全面。很多人不是有意要出bug的,但是确实是不知道啊,不知道要考虑情况A,情况B,不知道JVM底层的实现,所以有可能会产生的意想不到的结果。出了问题了也不知道往哪个方向去想。
  4>java cas的概念
  cas:compare and swap,比较并交换
  java的concurrent包中借助cas实现了区别于synchronized同步锁的一种乐观锁。
  CAS利用CPU的CAS指令,同时借助JNI来完成java的非阻塞算法,其他的原子操作都是利用类似的特性完成的。java的concurrent包相对于使用synchronized性能提升也是主要依赖于它。


简单的自我介绍
1、写一个单例,自己写了懒汉模式和饿汉模式(源码在util中)
自己放的致命错误是:没有加关键字static
单例在内存中国保存唯一性,在于1、通过构造函数私有化,不能通过new进行创建对象 2、通过static保证内存中只存在一个对象。注意字段和方法上都要加关键字
二面提到单例在那些情景中应用到:
自己只答了在spring容器的bean,就是应用到单例模式
还可以答:
在数据库连接的时候,用单例,不要每次连接数据库,都创建会话session
2、然后面试官问自己哪方面擅长一点,我就答了多线程这一块
面试官问线程启动的低层实现,就是start方法,自己不知道低层是咋实现的,回答了线程的生命周期,并画图出来了,其中写了创建线程、启动、运行、结束线程,其中会进行线程阻塞,包括线程资源占用,调用wait方法、其他线程让出cpu比如sleep、yeild。
这个画出来,面试官挺高兴的。
3、然后问wait是Thread方法么
不是,是object方法,追问为什么
问题的点1:object是一切类的基类,Thread也是继承object类,故它也可以调用wait方法。
问题的点2:为什么不将wait方法放在Thread,而放在object中。是因为线程对每个对象进行操作时,都是获取该对象的锁就是monitor(即锁),然后通过这个对象来操作。若当前线程等待的资源不满足,就通过这个对象,进行线程挂起。若是通过线程操作,因为当前线程可能会等待多个线程的锁,那么他就要通知多个线程,这样就非常复杂。
这个当前答的非常混乱,但是思想是对的
4、问了线程的实现方式
(1)通过实现runnable
(2)通过继承Thread类
(3)通过ExecutorService实现线程池,然后重写callable中的call接口,将线程返回值保存在future中
5、基于这个ExecutorService,问线程池低层是怎么实现的
真是该死,上次一点资讯就问到了线程池创建的两种方式是什么,那时就没有答出来。面试时介绍了coreSize与max,线程的核心数和最大数之间的变动。讲的很烂,结果面试官问,你是对那个类,进行低层源码看的,这个都没回答出来。答的是ExecutorService,应该是ThreadPoolExecutor。
ThreadPoolExecutor的核心参数
corePoolSize:核心池大小
maxmunPoolSize:线程池最大线程数
keepAliveTime:线程没有任务执行时最多保持多久会终止(注意只有线程数大于corePoolSize时才会起作用,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的数目小于corePoolSize)
Unit:keepAliveTime的单位时间
workQueue:一个阻塞队列,用来存储等待执行的任务。一般使用LinkedBlockingQueue
(基于链表的队列)
threadFactory:线程工厂,主要用来创建线程
Handler:表示拒绝处理任务时的策略(1、丢弃任务抛出异常2、丢弃任务,不抛出异常3、丢弃队列最前面的任务,重新尝试执行任务 4、调用线程处理任务)
ThreadPoolExecutor的核心方法:
(1)execute是ThreadPoolExecutor的核心方法,通过这个方法向线程池提交一个任务,submit也是向线程池提交一个任务,但是不同的是它有返回值(通过future来获取任务执行结果)
(2)shutdown()(处于该状态线程池不能接受新的任务,它会等待所有任务执行完毕)和shutdownNow()(尝试终止正在执行的任务)是关闭线程池
线程池执行的过程:
1)通过ThreadPoolExecutor创建线程池(包括corePoolSize的大小、maximum -PoolSize的大小、keepAliveTime的时间、keepAliveTime的单位、workQueue工作队列)
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,new ArrayBlockingQueue (5));
2)然后创建任务
创建的任务,只是实现了runnable接口
3)并将任务提交到线程池
executor.execute(myTask);
任务放入线程池会出现几种情况
(1)线程池中有空闲的线程,那么任务一来,线程就执行任务了
(2)线程中没有空闲的线程,就是任务数量大于corePoolSize,这时候,就将任务放入阻塞队列中,此时线程池就会启动补错措施,在创建线程,新创建的线程小于maximunPoolSize,新创建的线程从阻塞队列中取任务执行。当任务数小于maximunPoolSize时,空闲的线程空闲的时间达到keepAlive,就会消亡,直到线程数小于corePoolSize.
6、写了一个二分查找
面试官说代码可能造成内存溢出,我查看了一下,添加了一下输入的判断,这个因为可能造成数组越界。这些代码在编译器中也运行了,没有错误,可能是面试官自己弄错了
7、然后问了二叉排序树、二叉平衡树
什么是二叉排序树,二叉排序树的时间复杂度是多少,二叉排序树存在什么问题
(1)二叉排序树是左子树都比根结点小,右子树都比根结点大,且左右子树也是二叉排序树
(2)二叉排序树的时间复杂度是logn(一定要记牢了)
(3)二叉排序树在最好的状态像折半查找的判定树,最差的是排好序的单支树
为了解决最差排好序的单支数,引入了二叉树上结点的平衡因子,就是二叉树任何一个结点的绝对值不大于1,这就是平衡二叉树。记住平衡二叉树的左右旋转
8、二叉排序树的实现
美团1面总结:
错误1:写单例太粗心,少了static,保证字段和方法的唯一性(致命错误),还有在main方法中怎么调用单例实例,自己也优点蒙,虽然写的是对的,感觉还是不自信
错误2:在多线程中,自己wait方法为什么是object方法,而不是Thread方法,解释的不是很到位,还有线程池,说的太乱了
错误3:二叉排序树在有序时,形成单支数,查找效率很低,二叉平衡树,就是解决这种有序情况,是每个结点的平衡因子绝对值不大于1.还有写二叉排序树,写的太慢,还没写完
虽然第一面过了,但是错误很多,致使评价不是很高

1.MYSQL引擎和索引 2.进程间切换
答1.hashtree和b+tree 具体也没扯多少 2.完全不会

一面(2个小时)
java 基础
并发包concurrent等底层原理,反射原理、实现方式,java内存分配,java gc,CMS策略
框架 spring
框架比较,优缺点,依赖注入,spring ion实现,spring事物控制,spring循环依赖
hive&hadoop
hive distinct,group by,join on,group by count(distinct 紧张回答有缺陷)底层实现原理
调度系统,并发任务
算法
hadoop矩阵加和求均,归并排序 (纸上写代码,一般,真心不适应)
nice事情
自动excel,自动报表,自动还原建表语句,自动备份脚本
二面
hive 坑,详细描述
系统架构设计
设计数据平台,考虑强壮型、兼容性、
算法
关于一个二叉树的算法

聊技术,也是我中国科学院大学的,手写atoi,单例模式,Linux命令,常用的类,源码阅读,软件工程等等,感觉答的也挺好的。
三面,team leader,手写生产者消费者模式,手写范围覆盖,都没写出来,哎哎哎。然后给个实际的应用场景,多线程,多进程,通信。光着一个场景差不多问了半个小时。感觉我基础还行,但不会写代码也是个事啊,脑抽啊,其实是可以写出来的,只是写的慢,面试官面前不容易写而已,我去,跟总监讨论了下,说是确实不能发offer,欢迎随时来实习。随时来实习,实习。
十天后,逢美团内推,又推了一次,team leader让过来跟总监谈谈,就我的项目跟总监谈了40分钟左右,主要是多线程,给我设置相应的场景,让我发挥,可能发挥不太好吧,让我回去等通知,然后就没有然后了。
四面,最后没有拿到offer,美团真的很喜欢手撕代码啊,亲们,想进美团,从手撕代码开始吧!

[1,2],[3,5],[6,9], 再给你个范围比如[4,10],让你输出合并后的范围,即insert interval,手撕代码~
答然后就没有手撕出来,然后就没有然后了~

一面TCP/IP三次握手,四次挥手画图解释线程状态画图说明单例模式,如何实现线程安全的单例模式 手写代码linux常用命令知道哪些100以内的随机数排序怎么做手写代码数据库怎么优化--我记了概念非得深入问怎么看慢查询日志垂直拆分,水平拆分怎么做的等一系列为什么数据库索引使用B+树分布式缓存有没有用过radis与memcache的区别死锁,怎么解决死锁银行家算法,怎么实现,手写代码事务的四个特性spring的AOP原理代理模式的原理与应用项目相关。
我做的敏感词过滤。(汉语的敏感词要做分词么。我觉得不需要呀)讨论一会分词什么的二面进程与线程的区别java虚拟机GC,full GC触发条件,分区单例模式又问了一遍手写两个代码逆转单链表两个字符串的最大公共子序列http与https的区别没错linux的常用命令又问了一遍查看进程的命令查看日志的命令线程池的实现原理项目中还用到什么模式三面项目相关怎么设计表,设计模块,介绍自己做了什么,说说自己项目的亮点设计一个实名认证系统,主要功能是对名字打分(我说的几种他都不太满意)项目问完就开始聊人生。
一面:1、A和B两个用户同时插入两条相同的数据,如何保证表里面只有一条(不知道想要什么结果,懵逼)2、数据库的ACID特性3、项目用到RESTFul,实现机制,HTTP请求报文格式、Head Line里面有哪些参数?keep-alive作用4、TCP三次握手和4次挥手5、三次握手时要是服务端的服务没开TCP协议栈怎么处理?(懵逼。。。后来用telnet,curl这些tcp服务测试了一下,客户端会尝试三次SYN请求,服务器响应三次RST,然后结束链接)6、关闭连接时Time_Wait的作用7、算法:二叉查找(听到算法题就感觉要GG了,感觉被打发了。)
二面:前面聊了下项目,感觉被嫌弃了。问了jetty+jersey如何实现REST风格server,Hive和Hbase元数据存储机制等等,只知道一些最基础的东西,说了些表面,感觉面试官大佬很不满意,冷不丁来一句:你觉得你这个项目有哪些技术难点?我无言以对。后来估计感觉没什么聊的了居然问了下我数学建模的经历,元胞自动机、模型啥的,两年多了,一毛都不记得了。GG

1.什么是线程安全和非线程安全。
2.hashmap为啥是线程不安全的。
3.里边哪个方法导致不安全。
4.一个递归的小算法。
5.hibernate获取数据连接的过程。
6.Arraylist和linklist。
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
7.concurrenthashmap。
8.线程有几个状态。
9.mysql索引类型。
10.设计模式,当场写一个单例模式,又结合高并发,怎么保证线程安全。
11.spring事务管理。
等等。。。唉,只能说自己太说了,面试之前没准备好,白瞎了一次机会,好好准备一下,不难。祝你们成功。

volitle深入理解
TOPK 算法
设计模式 策略模式和命令模式 有什么区别,在工作中是怎样用的?
单机CPU过高怎样排查

一面:算法题,两个有序数组查找中位数聊聊平时做的项目给了一个大数据排序题目,亿万级别的用户访问数据,计算出Top10 的UV从单机版的实现,到分布式的实现。
二面:用AtomicBoolean如何实现自旋锁Disruptor中的一些细节,回答的并不是很好。Java中的几种队列。
三面:总监面试,问了自己在做爬虫过程中的一些内容。反爬虫如何实现,做爬虫过程中的一些细节

如何找到一个链表的位于中间的元素。
设置两个指针,p1,p2, 开始p1,p2均位于链接的头部。
p1 每次步进两步,
p2 每次步进一步
当p1到达链表的末尾时,p2所在的位置就是链表的中间元素

现在面了一轮,让写排序算法,以及基本的递归算法,问了非关系型数据库,还有java的基础知识,比如哈希


1 http 请求与相应的报文内容包含什么 2 spring Aop 解决方案具体忘了 3 打开网页慢,什么原因造成的,采取什么优化方式 4 sql 两道题 5 关于redis 登陆次数的问题 6 运算符 7 数据库索引的数据结构原理, 会带来什么影响 。

如果redis崩了,所有并发涌向后台数据库,你怎么处理。
面试题有点难度(1)AOP的实现方案(2)mysql的优化策略(3)索引的内部数据结构是啥

索引种类:B+索引和位图索引
表数据字段导入错误,如何变更
spring中事物传播性
Spring service本类中方法调用另一个方法事务不生效问题
http://blog.csdn.net/dapinxiaohuo/article/details/52092447
http://blog.csdn.net/aya19880214/article/details/50640596
同类调用 和 类A调用类B

spring事物中aop
mybatis中二级缓存踩过的坑
mybatis缓存是基于namespace的 如果有crud操作 会删除本地缓存

redis使用的场景
项目中redis的场景
string list hash
redis分布式锁
通过sexnx 设置 对应设置过期时间
redis批量操作
单例模式
elk 中e的优化 解释是怎样工作的
websocket 几次握手 使用的场景


http://blog.csdn.net/zuoanyinxiang/article/details/50890322

ArrayList和LinkedList的大致区别:
1)ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 (LinkedList是双向链表,有next也有previous)
2)对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3)对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

Spring—AOP两种代理机制对比(JDK和CGLib动态代理)
Spirng的AOP的动态代理实现机制有两种,分别是:
1)JDK动态代理:
具体实现原理:
1、通过实现InvocationHandlet接口创建自己的调用处理器
2、通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理
3、通过反射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型
4、通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数参入
JDK动态代理是面向接口的代理模式,如果被代理目标没有接口那么Spring也无能为力,
Spring通过java的反射机制生产被代理接口的新的匿名实现类,重写了其中AOP的增强方法。
2、CGLib动态代理
CGLib是一个强大、高性能的Code生产类库,可以实现运行期动态扩展java类,Spring在运行期间通过CGlib继承要被动态代理的类,重写父类的方法,实现AOP面向切面编程呢。
两者对比:
JDK动态代理是面向接口,在创建代理实现类时比CGLib要快,创建代理速度快。
CGLib动态代理是通过字节码底层继承要代理类来实现(如果被代理类被final关键字所修饰,那么抱歉会失败),在创建代理这一块没有JDK动态代理快,但是运行速度比JDK动态代理要快。
使用注意:
如果要被代理的对象是个实现类,那么Spring会使用JDK动态代理来完成操作(Spirng默认采用JDK动态代理实现机制)
如果要被代理的对象不是个实现类那么,Spring会强制使用CGLib来实现动态代理。

那么如何选择的使用代理机制了?
通过配置Spring的中标签来显示的指定使用动态代理机制 proxy-target-class=true表示使用CGLib代理,如果为false就是默认使用JDK动态代理

操作系统之页面置换算法
1.最佳置换算法(OPT) (理想置换算法):从主存中移出永远不再需要的页面;如无这样的页面存在,则选择最长时间不需要访问的页面。于所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。
2.先进先出置换算法(FIFO) :是最简单的页面置换算法。这种算法的基本思想是:当需要淘汰一个页面时,总是选择驻留主存时间最长的页面进行淘汰,即先进入主存的页面先淘汰。其理由是:最早调入主存的页面不再被使用的可能性最大。
3.最近最久未使用(LRU)算法 :这种算法的基本思想是:利用局部性原理,根据一个作业在执行过程中过去的页面访问历史来推测未来的行为。它认为过去一段时间里不曾被访问过的页面,在最近的将来可能也不会再被访问。所以,这种算法的实质是:当需要淘汰一个页面时,总是选择在最近一段时间内最久不用的页面予以淘汰。
4. 时钟(CLOCK)置换算法
LRU算法的性能接近于OPT,但是实现起来比较困难,且开销大;FIFO算法实现简单,但性能差。所以操作系统的设计者尝试了很多算法,试图用比较小的开销接近LRU的性能,这类算法都是CLOCK算法的变体。

构成死锁的4个条件
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

你可能感兴趣的:(java面试题)