下面为拼多多、饿了么、蚂蚁金服、哈啰出行、携程、饿了么、2345、百度等公司给我留下较深印象的一些java面试题
1. Private修饰的方法可以通过反射访问,那么private的意义是什么
答:1.java的private修饰符并不是为了绝对安全性设计的,而是对用户常规使用java的一种约束。2.从外部对对象进行常规调用时,能够看到清晰的类结构。
2. Java类初始化顺序
答:基类静态代码块,基类静态成员字段(并列优先级,按照代码中出线的先后顺序执行,且只有第一次加载时执行)-》派生类静态代码块,派生类静态成员变量(并列优先级,按照代码中出线的先后顺序执行,且只有第一次加载时执行)-》基类普通代码块,基类普通成员字段(并列优先级,按照代码中出线先后顺序执行)-》基类构造函数-》派生类普通代码块,派生类普通成员字段(并列优先级,按照代码中出线先后顺序执行)-》派生类构造函数
3. 对于方法区和永久区的理解以及他们的关系
答:方法区是jvm规范里要求的,永久区是Hotsport虚拟机对方法区的具体实现,前者是规范,后者是实现方式。jdk1.8做了改变
4. 一个Java文件有3个类,编译后有几个class文件
答:3个 文件中有几个类编译后就有几个class文件。
5. 局部变量使用前需要显示的赋值,否则编译通过不了,为什么这么设计
答:对于成员变量来说,其赋值和取值的访问先后顺序有不确定性,编译器确定不了,交给jvm去做比较合适。对于局部变量而言,其赋值和取值访问顺序是确定的,这样设计是一种约束,可以减少使用者犯错的可能。
6. ReadWriteLock读写之间互斥吗
答: ReadWriteLock读写锁,使用场景可分为读/读,读/写,写/写,除了读与读之间是共享的,其他都是互斥的。
7. Semaphore拿到执行权的线程之间是否互斥
答:Semaphore可有多把锁,可允许多个线程同时拥有执行权,这些执行权的线程并发访问同一对象,会产生线程安全问题。
8. 单例有几种实现方式
饿汉,懒汉,静态内部类,枚举,双检锁。
多线程下保证线程安全用双检索,为什么要2次校验,对象加上volatile关键字,原子性可见性,java内存模型,类的加载过程。
public class Singleton {
private Singleton(){
}
public volatile static Singleton instance;
public static Singleton getInstance(){
if(null == instance){
synchronized (Singleton.class){
if(null == instance){
instance = new Singleton();
}
}
}
return instance;
}
}
9. B树跟B+树是解决什么样的问题的,怎么演化过来,之间的区别
答:mysql索引的实现原理。二叉树会产生退化线象,提出来平衡二叉树,怎样养每一层放的节点多一些来减少遍历高度,引申出m叉树, m叉树有退化现象,引出m叉平衡树,也就是B树,这时候每个节点即放了key也放了value,怎么样将每个节点放尽可能多的key值,以减少遍历高度(访问磁盘次数),可以将每个节点只放key值,将value值放在叶子节点,在叶子节点的value值增加指向相邻节点指针,这就是优化后的B+树。
10. 写一个生产者消费者模式
生产者消费者模式,synchorized锁住一个LinkedList,一个生产者,只要队列不满,生产后往里放,一个消费者只要队列不空,向外取,两者通过wait()和notify()进行协调,如何提高效率 :消息队列
11. 写一个死锁
定义2个arraylsit,加上锁A,B。线程1,2。1拿着锁A,请求锁B,2拿住了锁B请求锁A,在等待对方释放锁的过程知乎谁也不让出已获得的锁。
public static void main(String[] args) {
final List<Integer> list1 = Arrays.asList(1,2,3);
final List<Integer> list2 = Arrays.asList(4,5,6);
new Thread(new Runnable() {
@Override
public void run() {
synchronized (list1){
for(Integer i : list1){
System.out.println(i);
}
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
synchronized (list2){
for(Integer i : list2){
System.out.println(i);
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (list2) {
for (Integer i : list2) {
System.out.println(i);
}
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
synchronized (list1){
for (Integer i : list1) {
System.out.println(i);
}
}
}
}
}).start();
}
12. CPU 100%怎么定位
13. String a = “ab”;String b = “a” + “b”;a == b是否相等 相等
14. int a =1 是原子性操作吗 是
15. 使用for循环删除ArrayList的特定元素吗
不行 重复的只能删除一个
用iterator
public static void reverse(){
List<String> list = new ArrayList<>(Arrays.asList("a","b","c","d"));
System.out.println(list);
Iterator<String> iterable = list.iterator();
while (iterable.hasNext()){
String element = iterable.next();
iterable.remove();
}
System.out.println(list);
}
16. 新的任务提交到线程池,线程池如何处理
第一步:判断工作队列是否已满,如果不是,创建一个新的工作线程来执行任务,如果核心线程池里的线程都在执行任务,则执行第二步。
17. AQS和CAS原理
AQS是抽象队列同步器 AQS实际上是以双向队列的形式连接所有的entry,比如ReentrantLock,所有等待的线程都被放在一个Entry中连接成双向队列。
比较并交换CAS,假设有三个操作数:内存值V,旧的预期值A,要修改的值B。当且仅当A与V的值相同,才会修改B的值并返回true,否者什么都不做返回false,比较并交换是一个原子操作,CAS一定要volatile变量配合。
CAS问题:
1.循环时间长
2.只能保证一个共享变量的原子操作
3.ABA问题
18. synchronized实现原理
设计到2条指令:monitorenter,monitorexit; 再说同步方法,从同步方法反编译的结果来看,方法的同步并没有通过指令monitorenter和monitorexit来实现,相对于普通方法,其常量池多了ACC_SYNCHORIZED标识符。
JVM是根据该标识符来实现方法的同步的:当方法被调用时,调用指令将会检查方法的ACC_SYNCHORIZED访问该标识符是否被设置,如果设置了,执行线程将先获取monitor,获取成功后才能执行方法体,方法体执行完后在释放monitor。在执行方法期间,其他任何线程都无法再获得同一个monitor对象。
19. volatile指令,指令重排
volatile可以保证可见性,每次读取volatile变量,一定是最新的数据。
底层代码执行不像Java 程序这么简单,它的执行是java代码-》字节码-》根据字节码执行对应的c/c++代码-》c/c++代码被编译成汇编语言-》和硬件电路交互,现实中,未来获取更好性能JVM可能会对指令进行重排序,多线程下会出现一些意想不到的问题。volatile禁止重排序,一定程度降低了代码执行效率。
20. AOP IOC
21. spring怎么样解决循环依赖
22. dispatchServlet怎么分发任务
23. mysql给离散度低的字段建立索引会出现什么问题。
24. HashMap既然有hash排序,还需要equals干什么
hashcode相同,元素对象也不一定重复
hashcode不同,元素对象一定不重复
equals判断最精确的,用hashcode做第一步判断是为了提高程序的效率。
25 jvm gc复制算法怎样实现
26. 注解的原理
27. 进程间通信的方式
28. ReentrantLock是可重入锁,什么是可重入锁
29. 线程执行过程遇到异常发生什么 怎么处理
30. HashMap.put元素发生冲突,为什么使用LinkedList(拉链法)而不用ArrayList
31. Object object = new Object()初始化的顺序 在jvm各区域做了什么
32. 线程怎么样按顺序执行