[面试] 面试题

[面试] 面试题

标签(空格分隔): java


写文章
Java研发方向如何准备BAT技术面试(超级干货) https://zhuanlan.zhihu.com/p/22202533#!

Java部分

1. [美团]HashMap和HashTable的区别。HashMap底层的实现机制:负载因子、冲突解决方式。Java8的优化。
    - HashMap和TreeMap的区别
    - HashMap遇到Hash碰撞的时候,除了拉链法解决还有什么方法吗?
        - 开放定址法
        - 线性探测再散列法
        - 再Hash


2. [美团]string和stringbuffer的区别。String为啥不可变,在内存中的具体形态。String、StringBuffer、StringBuilder
    - 都是Final类,都不能被继承,都不能被修改;
    - String长度不可变,StringBuffer和StringBuilder长度可变;
    - StringBuffer线程安全,StringBuilder线程不安全;
    - 效率:String>StringBuilder>StringBuffer

3. [阿里]comparable接口和comparator接口实现比较的区别和用法,Arrays静态类如下实现排序的。
     - Comparable:可以和自己比较
     - Comparator:不支持和自己比较。比较的是两个相同类的实例。更加灵活。
    http://www.cnblogs.com/szlbm/p/5504634.html
     - Arrays下的排序是改进的快排。

4. [阿里]java中的异常机制。
    Throwable 万物皆可抛;
        - Exception:[需要程序处理]
             - 编译时异常:必须用try...catch捕捉,否则编译不通过。
             - 运行时异常:不确定性。主要由逻辑问题产生。
        - Error:[不需要程序处理]交给JVM处理,JVM大多数情况下选择终止进程。如OutOfMemoryError。
    异常处理步骤:
        1. 一旦产生异常,就会创建一个异常类的实例化对象。
        2. 在try语句中对此异常进行捕捉。
        3. 异常对象对catch中的各个异常类型进行匹配,如果匹配成功,则执行catch代码块中的代码。

5. [阿里]java线程阻塞调用wait函数和sleep区别和联系,还有函数yield,notify等的作用。
    - 经典Wait/Notify范式
    - sleep:
        - 是Thread的静态方法。
        - 调此方法会让当前线程暂停执行,并将CPU让给其他线程。但是对象的锁依然保持,因此休眠结束会自动恢复(恢复到就绪状态)。
    - wait:
        - 是Object的方法。
        - 调用对象的await方法。会导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify方法或notifyALl(),才能唤醒等待池中的线程进入锁池(Lock pool),如果线程重新获得对象的锁,就会进入就绪状态。

6. ThreadLocal用过么,原理是什么,用的时候要注意什么
    作用:
        解决多线程程序的并发问题提供了一种新的思路。
        为线程维护一个变量的副本。
        为每一个使用该变量的线程分配一个独立的变量副本,所以每一个线程都可以独立的改变自己的副本,而不影响其他线程所对应的副本。
    原理:
    public class MyThreadLocal {
        private Map map = Collections.synchronizedMap(new HashMap());
        
        public void set(T newValue) {
            //Key:线程对象
            //Value : 变量副本
            map.put(Thread.currentThread(), newValue);
        }
        
        public T get() {
            return map.get(Thread.currentThread());
        }
        
        public void remove() {
            map.remove(Thread.currentThread());
        }
    }
    使用:
        void set(T value):设置当前线程的线程局部变量的值。
        T get():获得当前线程所对应的线程局部变量的值。
        void remove():删除当前线程中线程局部变量的值。

7. [阿里]接口和抽象类有什么区别?
    - 如果接口和抽象类都可以使用,优先使用接口,避免抽象类的单继承局限;
    - 方法实现:抽象类-可以有方法的实现。接口-不能;
    - 方法修饰符:抽象类-方法有public,protect,default等修饰。接口-默认public,不可以使用其他修饰符;
    - 构造器:抽象类-有;接口-没有;
    - 多继承:抽象类-可以继承一个类和实现多个接口;接口-只能实现多个接口;
    
            
8. [挖财]有哪些无锁的数据结构?无锁实现的原理?
    - ConcurrentHashMap
      ConcurrentLinkedQueue
    - 实现原理:
        CAS(V,E,N):V-原来的值,E-预期的值,N-新值
        CompareAndSwap:在set之前先比较该值是否发生变化,只有在没有变化的情况下 才对其赋值。
    > http://blog.csdn.net/liubenlong007/article/details/53761730
    
    cas是什么,他会产生什么问题(ABA问题的解决,如加入修改次数、版本号)
    
    
9. [阿里]take,poll的区别?put,offer的区别?
    * take():如果队列中没有元素,则线程wait,释放CPU;
    poll():线程不会等待,直接返回null;
    * put():如果队列满的时候,线程会wait,释放CPU;
    offer():如果队列满的时候,线程不会等待,直接返回false;
    带*表面是阻塞方法;
    注意:如果使用while(true)的时候,千万不要用poll,CPU为占用100%。
    
    pop:相当于get的操作,就是只是查看。从此列表所表示的堆栈处弹出一个元素。
    poll:相当于先get然后再remove掉,就是查看的同时,也将这个元素从容器中删除掉。
    

10. [美团]synchronized、Lock之间的区别。
11. [美团]线程池的优点和实现机制。
    - 优点:
        1. 降低资源消耗;
        2. 提高响应速度;
        3. 提高线程的可管理性;
        
    - 处理流程:
        当提交一个新任务到线程池时,
        1. 判断如果`核心线程池`是否已满。如果未满,则创建线程;如果已满,则下一步;
        2. 判断`工作队列`是否已满。如果未满,则将新任务存储到工作队列中;如果已满,则下一步;
        3. 判断`线程池`是否已满。如果未满,则创建新线程执行任务;如果已满,则按照`饱和策略处理任务`;
    
    - 实现方式:
        1. Executors.newFixedThreadPool(int nThreads);
        适用于:为了资源管理需求,限制当前线程数量的场景;比较适用于负载比较重的场景;
        2. Executors.newSingleThreadPool();
        适用于:保证顺序执行各个任务;
        3. Executors.newCachedThreadPool();
        适用于:大小无界的线程池。适用于执行很多短期异步任务的小程序。
    
    - Executor框架的主要组成:
        1. 任务。Runnable、Callable接口。
        2. 任务的执行。ThreadPoolExecutorService/ScheduledThreadPoolExecutor。
        3. 异步计算的结果。Future接口和FutureTask类。
        
    - 线程池的使用:
        1. 线程池的创建
        2. 向线程池中提交任务
            - execute():用于提交不需要返回值的任务;
            - submit():用于提交需要返回值的任务,返回一个future类型的对象。get()方法会阻塞当前线程直到任务完成。
        3. 关闭线程池
            原理:遍历线程池中的工作线程,逐个调用线程的interrupt方法来中断线程。
            (什么是中断?CPU在正常运行时,由于内部/外部事件,引起CPU中断正常运行的程序,转到为内部或外部的程序中去运行)
            - shutdown()
            - shutdownNow()
        4. 合理的配置线程池
        5. 线程池的监控
        > http://blog.csdn.net/he90227/article/details/52576452

12. [挖财]Synchronized的底层如何实现?用在代码块上和方法上有什么区别?
    * 底层实现:
    * 用在代码块上和方法上的区别?
        - 用在代码块上是锁住`调用该方法的对象`,也可以是任何对象。
        - 用在方法上是锁住`调用该方法的对象`。
        - 用在代码块上是减小锁的粒度,从而提高并发性。
        - 总结:无论是用在代码块上还是用在方法上,都是获取对象的锁;每一个对象都只用一个锁与之关联;实现同步需要很大的系统开销,甚至容易造成死锁,所以尽量避免无谓的同步控制。
    * synchronized和static synchronized的区别?
        - synchronized是对类的当前`实例`进行加锁,防止其他线程访问**这个实例**的synchronized块。同一个类的不同实例不会有这种约束。
        - static synchronized控制的是`类的所有实例`,限制的是jvm中该类的所有实例的synchronized块。
        
13. [阿里]ConcurrentHashMap实现原理(锁分离技术、[挖财]默认容量、[挖财]什么时候扩容、[挖财]怎么扩容)
14. ReentrantLock可重入锁
    - 可重入锁
        ReentrantLock
        概念:支持一个线程对资源重复加锁。
        优点:(或者说为什么要用ReentrantLock?)
            ** 1. 可中断;(有两种类型:忽略中断锁和响应中断锁。)
                线程A在正在执行锁中的代码,线程B等待获取锁,但是由于B等待时间过长,线程B不想在等待了,于是B想先处理其他事情,它可以中断自己。
                - 如果此时ReentrantLock提供的是忽略中断锁,那么B将不会去理会中断,而是继续等待。
                - 如果此时ReentrantLock提供的是响应中断锁,那么B将放弃等待,去处理其他事情。
                获取响应中断锁的代码如下:
                ReentrantLock lock = new ReentranLock();
                ...
                lock.lockInterruptibly();//获取响应中断
                try{
                    ...
                }catch(){
                }finally{
                    lock.unlock();//锁必须在finally中释放
                }
            2. 可实现公平锁;
            3. 锁可以绑定多个条件;
            
        适用场景:
            1. 可中断、可定时、可轮训情况下。
            2. 公平队列。
    
    - 读写锁
        ReentrantReadWriteLock.ReadLock
        ReentrantReadWriteLock.WriteLock
        使用读写锁的原因:synchronized虽然读写互斥、写写互斥,但是也存在读读互斥。
            但是读读不会存在资源竞争,所以jdk5中提供了读写锁。
            ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
            rwl.writeLock().lock();//获取写锁
            rwl.readLock().lock();//获取读锁
    
    - 信号量
        Smaphore
        是一个功能完毕的计数器。
        作用:
            控制某个资源的同时被访问的任务数。
            acquire();//获取一个许可
            release();//释放一个许可
            如果同时被访问的任务数已满,则其他acquire的任务将进入等待状态,直到一个任务被release才能再次被acquire.
    
    - CyclicBarrier(又叫障碍器)
        你希望创建一组任务,它们并发地执行工作,另外的一个任务在这一组任务并发执行结束前一直阻塞等待,直到该组任务全部执行结束,这个任务才得以执行。
        //创建CyclicBarrier对象, 
        //并设置执行完一组5个线程的并发任务后,再执行MainTask任务 
        CyclicBarrier cb = new CyclicBarrier(5, new MainTask());
    
    - AQS[AbstractQueuedSynchronizer]
        - 底层实现是双向链表
        - 作用:
    
15. [挖财]volatile原理,volatile关键字如何保证内存的可见性?
    * 关键词作用:
        - 保证内存可见性
        - 防止重排序
        - 注意:volatile不保证原子性
    * 怎么保证内存可见性?
        - 内存直读
        - 禁止指令重排序
    * volatile使用建议
        - 当访问的变量在synchronize代码块中或者是常量时,没有必要使用volatile。
        - volatile屏蔽了JVM中必要的代码优化,所以效率比较低,所以在必要时才使用这个关键词。
    * volatile和synchronize的区别
        - volatile不会加锁
        - volatile类似于同步变量读写操作
        - volatile不如synchronized安全

16. 阻塞队列
    - 概念:
        当队列为满的时候,往队列中插入元素,队列阻塞,线程wait,同时释放cpu资源,线程进入`阻塞`状态。
    - JDK提供的7种阻塞队列:
        1. ArrayBlockingQueue:基于数组的有界阻塞队列,按照FIFO对元素进行排列。
        2. LinkedBlockingQueue:基于链表的有界阻塞队列,按照FIFO对元素进行排列。
        3. PriorityBlockingQueue:支持优先级排序的无界阻塞队列。
        4. DelayQueue:使用优先级队列实现的无界阻塞队列。
        5. SynchronizedBlockingQueue:不存储元素的阻塞队列。
        6. LinkedTransferQueue:基于链表的无界阻塞队列。
        7. LinkedBlockingDeque:基于链表的双向阻塞队列。
    - 实现原理:
        等待通知机制
    
17. LinkedBlockingQueue && ConcurrentLinkedQueue
    - LinkedBlockingQueue:线程安全,实现了FIFO,作为生产者消费者的首选。
    public class Demo{
        //装苹果的篮子
        class Basket{
            LinkedBlockingQueue basket =  new LinkedBlockingQueue(3);
            
            //生产苹果
            public void produce(){
                basket.put("苹果");
            }
            
            //消费苹果
            public String  consume(){
                return basket.take();
            }
            
        }
    
        //生产者线程
        class Producer implements Runnable{
            private Basket basket;
            
            Producer(Basket basket){
                this.basket = basket;
            }
        
            public void run{
                while(true){
                    try{
                        //生产一个苹果
                        basket.produce();
                        Thread.sleep();
                    }catch(Exception e){
                    
                    }
                }
                
            }
        }
    
        //消费者线程
        class Consumer implements Runnable{
            private Basket basket;
            
            Producer(Basket basket){
                this.basket = basket;
            }
        
            public void run{
                while(true){
                    try{
                        //消费一个苹果
                        basket.consume();
                        Thread.sleep();
                    }catch(Exception e){
                    
                    }
                }
                
            }
        }
    }
    - ConcurrentLinkedQueue:线程安全,实现了FIFO,底层采用CAS实现,保证元素的一致性。
    > http://www.cnblogs.com/linjiqin/archive/2013/05/30/3108188.html

18. CAP定理
    C:Consistency一致性
    A:Availability可用性
    P:Partition tolerance分区容错性
19. String类面试题
    1.判断定义为String类型的s1和s2是否相等
        String s1 = "abc";
        String s2 = "abc";
        System.out.println(s1 == s2);         //true                
        System.out.println(s1.equals(s2));     //true
    解释:
        1.String类型的字符串是常量,存储在常量池中,常量池中没有这个字符串对象,就创建一个,如果有直接用即可,所以s1和s2里面存储的是一样的地址。
        2.String类中的equals()方法重写了父类的,判断的是相同字符序列的字。
    
    2.判断定义为String类型的s1和s2是否相等
        String s1 = new String("abc");        //记录的是堆内存对象的地址值            
        String s2 = "abc";                             //记录的是常量池中的地址值
        System.out.println(s1 == s2);          //false
        System.out.println(s1.equals(s2));   //true
    
    3. 判断定义为String类型的s1和s2是否相等
        String s1 = "a" + "b" + "c";    
        解释:java中有常量优化机制,编译器编译的时候就会使其变成"abc"; 就像byte b = 3+4;在编译时就变成7,把7赋值给b,常量优化机制
        String s2 = "abc";            
        解释:由于上句就已经在常量池中创建了"abc"了,所以就直接用就行了
        System.out.println(s1 == s2);        //true
        System.out.println(s1.equals(s2));//true
    4. 判断定义为String类型的s2和s3是否相等
        String s1 = "ab";
        String s2 = "abc";              // 记录的是常量池的地址值
        String s3 = s1 + "c";           // 存储的是堆内存中的地址值
        System.out.println(s3 == s2);            //false
        System.out.println(s3.equals(s2));    //true
    解释:1.s1指向常量池中的"ab";s2指向常量池的"abc";
        2.s1 + "c";字符串串联是通过 StringBuilder(或 StringBuffer)类及其append方法实现的。字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。也就是说s3里面存储的是堆内存中的地址值。
        3.s2记录的是常量池的地址值,s3记录的是堆内存中的地址值,所以是false

20.两个对象相互equals的话,hashCode一定相同吗?什么时候需要重写hasCode?
    - 一定相同。反之,则不然。
    - 为何会有这样的要求?
    在集合中,比如HashSet中,要求放入的对象不能重复,怎么判定呢?
    首先会调用hashcode,如果hashcode相等,则继续调用equals,也相等,则认为重复。
    如果重写equals后,如果不重写hashcode,则hashcode就是继承自Object的,返回内存编码,这时候可能出现equals相等,而hashcode不等,你的对象使用集合时,就会等不到正搜索确的结果

Java8

1. 函数式接口
    概念:在接口中添加一个抽象方法
    定义:
    1. 在一个接口中只能定义一个**唯一**的抽象方法。
    2. 通过注解 FuntionInterface
    特性:
    1. 函数式接口必须定义静态方法。
    2. 允许定义java.lang.Object里的public方法

2. Lambda表达式
3. 接口增强
4. 集合流式操作

设计模式

1. 面向对象开发的六个原则
    - 单一职责
    - 开放封闭
    - 里氏替换
    - 依赖倒置
    - 合成聚合
    - 接口隔离
    
2. 迪米特法则
    也叫最少知道法则。一个对象对其他对象应该尽可能**少**的了解。

3. 单例模式
4. 工厂模式

计算机网络

1. [美团]TCP三次握手、四次挥手,为什么建立连接是三次,断开连接是四次?
    - 为什么握手不是两次?
        为了因为网络延迟而导致的重复链接。
    - 为什么断开是四次?
        因为服务端需要把未传输完的数据传输完。
[面试] 面试题_第1张图片
三次握手
[面试] 面试题_第2张图片
四次挥手
2. [美团]HTTP POST和GET的区别和联系。
3. HTTPS的传输过程
    - 怎么实现通信安全?
        HTTPS是用SSL、TLS协议来实现信息安全的。
    - Https是哪一层的协议?
        应用层
    - Http原来和TCP直接通信,加入SSL后,HTTP先和SSL通信,再由SSL和TCP通信。
    - SSL使用的是非对称加密算法。
    - HTTPS缺点:
        加解密比较耗时。
    - HTTPS是为了预防`中间人攻击`。
    - HTTP+加密+认证+完整性=HTTPS
[面试] 面试题_第3张图片
Https
4. TCP、UDP区别?
    - TCP:
        1. 面向连接
        2. 可靠的
    - UDP:
        1. 无连接的
        2. 尽最大努力交付
        3. 面向报文的
        4. 没有拥塞控制
5. 一次网络请求的过程?
    1. 根据域名查询IP。浏览器缓存->操作系统缓存->本地域名服务器缓存->域名服务器缓存。
    2. 得到IP后发起基于TCP的HTTP请求。如果浏览器存储了该域名下的cookie,那么会把cookie放入HTTP请求头里。 
    3. TCP被封装成IP包,通过网络(可能经过多个路由器、交换器)发送到IP地址对应的服务器。
    4. 服务器解析HTTP请求,生成HTTP相应后,将相应发送给HTTP客户端。
    5. 浏览器得到响应后,根据相应内容,显示结果。

操作系统

1. [美团]进程和线程的区别
    进程:程序的一次执行;
    线程:CPU调度的基本单位;
2. [美团]操作系统的内存管理

3. 死锁产生的原因?死锁的必要条件?死锁的预防?
    - 原因:
        1. 系统资源不足
        2. 系统推进顺序不当
        3. 资源分配不当
    - 必要条件:【只要系统发生死锁,这四个条件必然成立。】
        1. 互斥条件。一个资源每次只能被一个进程使用。
        2. 请求与保持条件。一个进程因请求资源而阻塞时,对已获得的资源保持不放。
        3. 不剥夺条件。进程已获得的资源,在末使用完之前,不能强行剥夺。
        4. 循环等待条件。若干进程之间形成一种头尾相接的循环等待资源关系。
    - 预防:
        只要破坏其中的任何一个条件,死锁就不会发生。
        1. 破坏互斥条件。

数据库

1. [美团]事务的四个特性,ACID
    * ACID
        - 原子性[Atomicity]:保证事务中的所有操作全部执行或者全部不执行。
        - 一致性[Consistency]:保证事务操作之前和之后都是一致的。
        - 隔离性[Isolation]:多个事务并发的话,应该和多个事务串行执行效果一致。
        - 持久性[Durability]:事务执行完之后,对于数据库的影响应该是持久的。
    * 脏读、幻读、不可重复读:
        - 脏读:一个事务读取了另一个事务`未提交的数据`,而这个数据有可能被回滚。
        - 幻读:事务不同独立执行时发生的一种现象。事务1读取指定Where条件的结果集,然后事务2插入一条新数据,而这条新数据刚好满足事务1所查询的条件,然后事务1再次查询时,看到了事务2新提交的数据。【幻读强调的是新增、删除。同样的条件,两次查询的记录数不同】
        - 不可重复读:在一个事务范围内,两次查询得到不同的结果。【不可重复读强调的是修改。同样的条件,两次查询的记录值不同】
    * 事务隔离级别
        - 串行化:保证所有情况下都不会发生。【锁表】
        - 可重复读:会出现幻读。【会锁定所读取的所有行】
        - 读未提交:会出现脏读、幻读、不可重复读。【隔离级别最低,并发性能高】
        - 读已提交(默认): 会出现幻读、不可重复读。【锁住正在读取的行】
        总结:四个级别逐渐增强。每个级别分别解决一个问题,事务级别越高,性能越差,大多数环境下ReadCommit情况下就可以了。
2. [美团]常见索引的实现原理,底层的数据结构b+树?
3. [美团]嵌套查询、关联查询等SQL语句的书写
        交叉连接(自然连接、笛卡尔积)
        内连接(等值连接)
        外链接:左外、右外、全外
        自连接
        http://www.voidcn.com/blog/990487026/article/p-5689433.html
        having和where的区别
        子查询
4. [美团]常见慢查询优化的方式。
5. [美团]常见索引,innodb和myISAM的区别,innodb的底层实现机制,索引前缀的概念,B+数据结构。
为什么常见索引采用B+树的数据结构而不是平衡二叉树?
    - 常见索引:
        1. 直接创建索引、间接创建索引
        2. 普通索引、唯一性索引
        3. 单个索引、复合索引
        4. 聚簇索引、非聚簇索引
    - MyISAM和InnoDB的区别:
        1. 事务。Innodb支持事务、MyISAM不支持事务
        2. 锁。Innodb:行锁、MyISAM:表锁。
        3. MVCC。Innodb支持多版本并发控制,MyISAM不支持
        4. 外键。Innodb支持外键、MyISAM不支持外键。
        5. 全文索引。Innodb不支持全文索引、MyISAM支持。
    - MyISAM和InnoDB的区别:
        - MyISAM是非事务安全的,InnoDB是事务安全的。
        - MyISAM的锁是表级别的,InnoDB是行级别的。
        - MyISAM支持全文检索,InnoDB不支持全文检索。
        - MyISAM相对简单,所以效率上要高于InnoDB,小型应用可以考虑MyISAM。
        - MyISAM保存的是文件的形式,在跨平台数据转移中会比较方便。
        - InnoDB表比MyISAM表更安全,可以在保证数据不丢失的情况下,将非事务表转到成事务表。(alter table tablename type = innodb)

6. [美团]给出具体的业务场景,分析数据库表索引的设计。
    - 手写索引
        alter table table_name add index index_name(column_list)
        create index idx_name on table_name(column_list)
    - 索引适用场景:
        1. 经常order by 、group by distinct 后面的字段
        2. 在union等集合操作的结果集字段
        3. 经常查询的字段
        4. 经常用在表连接上的字段
        5. 很少被更新的字段
    - 索引失效场景:
        1. 如果条件中有or,即是其中有条件带索引也不生效
        2. like 查询是以%开头
        3. 如果类型是字符串,则一定要在条件中使用引号引起来,否则不会使用索引
        4. 如果mysql估计使用全表扫描要比使用索引快,则不使用索引
        此外,查看索引的使用情况
        show status like ‘Handler_read%';
        大家可以注意:
        handler_read_key:这个值越高越好,越高表示使用索引查询到的次数
        handler_read_rnd_next:这个值越高,说明查询低效
7. [京东]索引在什么情况下会失效?
8. redis redis,memcache底层客户端使用一致性Hash,看是否了解; redis的事件驱动多路复用底层实现;引申到NIO编程, 看对Netty,或mina是否了解。 如果候选者同时用过memcache,redis,看下是否了解两者在使用场景上的区别。以考察使用深度,以及是否有好奇精神。
9. 范式
    函数依赖
        1. 部分依赖
        2. 完全依赖
        3. 传递依赖
        平凡依赖、非平凡依赖
    多值依赖
    连接依赖
    - 范式:
    https://www.zhihu.com/question/24696366
        - 1NF:属性不可再分。
        - 2NF:属性完全依赖于主键。[消除部分依赖]
        - 3NF:属性不依赖于其他非主属性[消除传递依赖]
        - BCNF:在1NF上,任何非主属性不能对主键子集依赖[在3NF上消除对主码子集的依赖]
        - 4NF:要求把同一表内的多对多关系删除。[消除多值依赖]
        - 5NF:[消除连接依赖]
10. 数据库连接池的原理
11. 乐观锁、悲观锁
12. SQL注入的原理、如何预防?
    - SQL注入:
        
13. 索引的基本实现(b+树介绍、和b树、r树的区别)
14. 数据库索引的优缺点、以及什么时候数据库索引失效?
15. redis的存储结构
16. [阿里]事务是如果通过日志实现的?
17. [阿里]MySQL中InnoDB引擎的行锁加载什么上完成?为什么是这样子?
18. [阿里]你们数据库是否支持emoji表情,如果不支持,如何操作?
如果是utf8字符集的话,需要升级至utf8_mb4方可支持

java虚拟机

1. [美团、阿里]JVM内存模型,每个区域存放的内容。Jvm内存分代机制(会问分为那几个代,各个代特点),分代回收的优点(这个问了很多次)
2. [美团]JVM垃圾回收算法。
3. [美团]JVM类加载机制、双亲委派模型。

知识点

GC在什么时候,对什么东西,做了什么事情?
http://icyfenix.iteye.com/blog/715301

- 什么时间?
- 对什么东西?
- 做了什么事情?

算法

1. [美团]在一百个数中寻找重复数字,并对自己提出的算法进行更进一步的优化。
2. [美团]判断一个链表中是否有环。

框架部分

JavaWeb

1. Servlet的生命周期?Servlet是单例还是多例?线程是否安全?怎么处理多个同时的请求?
    - Servlet由Web容器创建。
    - 生命周期:
        - init(ServletConfig config)
        - service(ServletRequest req, ServletResponse resp)//根据需要调用doGet/doPost
        - destory();
    - 单例。
        单实例,减少产生servlet的开销。
    - 线程`不安全`。
    - 处理多请求:
        Servlet采用`单例多线程`方式处理。
        
2. forward和redirect的区别?
    - 请求转发:
        1. 客户端发出一次请求
        2. 地址栏不变
        3. 请求数据会共享
    - 请求重定向:
        1. 客户端发出两次请求
        2. 地址栏改变
        3. 请求数据不会共享

3. cookie和session的区别?
4. Jsp的9大隐式对象、四大作用域
    - 9大隐式对象:
        request
        response
        application
        session
        exception
        config
        page
        pageContext
        out
    - 4大域对象:
        - pageContext页面范围:
        - request请求范围:
        - session会话范围:
        - application应用范围:

5. Servlet和Filter的区别?
    - Servlet和Filter没有关系
    - 
6. web.xml中listener、filter、servlet的加载顺序?
    - contextParam -> listener -> filter -> servlet

Struts2

[面试] 面试题_第4张图片
Struts2工作流程图
1. Struts2的工作流程
    - 1. 客户端发起一个HttpRequest请求.
    - 2. 请求`顺序`经过一些列过滤器Filter.
        FilterDispatcher是Struts2控制器的核心。
    - 3. FilterDispatcher被调用,并询问ActionMapper来决定这个请求是否需要调用某个Action。
    - 4. 如果ActionMapper决定要调用某个Action,那么FilterDispatcher就会把请求给ActionProxy.
    - 5. ActionProxy通过Configuration Manager询问框架配置文件,找到需要调用Action类。
    - 6. ActionProxy会创建一个ActionInvocation实例。
    - 7. 在调用Action的前后会涉及到相关Interception的调用。
    - 8. Action执行完毕,ActionInvocation负责找到struts.xml中对应的返回结果。
    > http://blog.csdn.net/zzjjiandan/article/details/9837869
        
2. Struts2的拦截器和Sevrlet的过滤器有什么区别?   
    - 拦截器是Struts2的概念,实现方式不同(实现Interceptor init()/intercept()/destroy()),请求前拦截。
    - 过滤器是Servlet的概念,实现方式不同(实现Filter  init()/doFilter()/destroy()),请求前过滤,响应后过滤。
    
3. Struts2是单例吗?线程安全吗?
    - 多例。
    - 线程安全。
    
4. Strut2几种常见的配置文件的加载顺序?
       struts-default.xml
    -> struts-plugin.xml
    -> struts.xml
    -> default.properties
    -> struts.properties

SpringMVC

1. springmvc的controller是不是单例?线程安全吗?
    - 是单例.因为用的就是servlet.
    - 线程不安全。(原理同servlet)
        - 不要用同步,会影响线程。解决方案是:控制器中不要写成员变量。
    
2. SpringMVC和Struts的区别?
    - 1. 机制:springmvc的入口是servlet,strurts的入口是filter.(servlet和filter的区别)。
    - 2. 性能:springmvc会比struts快。
    - 3. 参数传递:struts用属性来接受参数传递,参数多方法共享。
    - 4. 设计思路:struts更符合oop思想。

3. SpringMVC工作流程?
    - DispatcherServlet(中央控制器)
        接受请求,调用HandlerMapping.
    - HandlerMapping(处理器映射器)
        解析XML文件或者注解,找到action对象的Handler.
    - HandlerAdapter(处理器适配器)
        根据Handler类的规则去执行Handler.
        返回给中央控制器ModelAndView.
    - ViewResolver(视图解析器)
        根据ModelAndView解析得到真正的View地址.
[面试] 面试题_第5张图片
SpringMVC工作流程

Spring

1. 什么是Spring框架?Spring框架有哪些主要模块?
2. 如何理解AOP中的连接点(JoinPoint)\切点(PointCut)\增强(通知Advice)\引介(Introduction)\织入(Weaving)\切面(Aspect)?
    - 连接点:程序执行的某个特定位置。
    - 切点:如果连接点相当于数据中的记录,那么切点相当于查询条件,一个切点可以匹配多个连接点。
    - 增强:增强是织入到目标类连接点上的一段程序代码。
    - 引介:一种特殊的增强。不是对方法的增强,而是对`类对象`的增强。
    - 织入
        - 编译器织入
        - 类装载织入
        - 动态代理织入
        Spring采用`动态代理织入`;
        AspectJ采用`编译器织入和类装载织入`;
        ------------------------------------------------------------------
        | Spring AOP底层就是用动态代理实现:                                        
        | - 如果目标类实现了若干接口,则使用JDK的动态代理;                         
        | - 如果目标类没有实现任何接口,则使用cglib的动态代理;                     
        |规则:                                                                     
        |   优先对接口代理(JDK代理),如果目标类没有实现任何接口,才使用CGLIB代理;
        ------------------------------------------------------------------
    - 切面:由`切点`和`增强`组成。

3. 什么是控制反转(IOC)?什么是依赖注入?
4. BeanFactory和ApplicationContext有什么区别?
    - ApplicationContext 是 BeanFactory 子接口,BeanFactory 才是Spring框架最核心工厂接口。 
    - ApplicationContext 是对BeanFactory 接口扩展, 企业开发很少直接使用BeanFactory 
    * ApplicationContext会在容器初始化时,对其中管理Bean对象进行创建, BeanFactory 会在对象获取getBean时才进行初始化 。
    
5. Spring有几种配置方式?
    - 1. XML方式装配;
    - 2. 注解方式装配;
    - 3. Java代码方式装配;
    
6. 请解释Spring Bean的生命周期?
    - 实例化BeanPostProcess(后处理器)
    - 执行Bean的构造器
    - 为Bean注入属性
    - 调用bean的init-method方法指定属性的初始化方法
    - 容器初始化成功
    - 调用bean的destory-method方法指定属性的方法
    
    ① Spring IoC容器找到关于Bean的定义并实例化该Bean。 
    ② Spring IoC容器对Bean进行依赖注入。 
    ③ 如果Bean实现了BeanNameAware接口,则将该Bean的id传给setBeanName方法。 
    ④ 如果Bean实现了BeanFactoryAware接口,则将BeanFactory对象传给setBeanFactory方法。 
    ⑤ 如果Bean实现了BeanPostProcessor接口,则调用其postProcessBeforeInitialization方法。 
    ⑥ 如果Bean实现了InitializingBean接口,则调用其afterPropertySet方法。 
    ⑦ 如果有和Bean关联的BeanPostProcessors对象,则这些对象的postProcessAfterInitialization方法被调用。 
    ⑧ 当销毁Bean实例时,如果Bean实现了DisposableBean接口,则调用其destroy方法。
    
7. Spring Bean的作用域之间有什么区别?Spring如何加载Bean?
    - singleton(默认)
    - prototype:多例。在工程getBean的时候才初始化。
    - request:每次Http请求都会创建一个实例。
    - session:同一个HttpSession会共享一个实例,不同的session共享不同的实例。
    - gobal session:全局会话。

8. Spring框架中的单例Bean是线程安全的吗?
    - 单例
    - 线程不安全
    
10. 请解释Spring的自动装配
    - @Autowired:按照类型装配。缺点:如果容器中存在两个相同类型的对象,无法注入。@Autowired + @Qualifier 指定注入Bean的id
    - @Resource:按照名称注入。
    
11. 构造方法注入和设值注入有什么区别?
    - 构造注入:先实例化`所依赖的对象`,再实例化本身。
    - 设值注入:先实例化`本身对象`,在实例化`所依赖的对象`。

12. Spring框架都用了哪些设计模式
13. Spring事务传播特性
    PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 
    PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。 
    PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。 
    PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 
    PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
    PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。 
    PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

Hibernate

1. Hibernate的工作原理?以及为什么要用?
    1. 读取并解析配置文件
    2. 读取并解析映射文件,创建sessionFactory
    3. 打开session
    4. 创建事务
    5. 持久化操作
    6. 提交事务
    7. 关闭session
    8. 关闭sessionFactory
    
2. Hibernate有几种数据查询方式?(5种)
    - 对象导航图
    - QID查询
    - HQL
        HQL和SQL的差别?
        - HQL面向对象,SQL操作关系数据库.
        - HQL仅适用于查询数据,不支持insert、update、delete操作.
    - QBC
    - 本地SQL
3. load和get的区别?
    Users user = (Users)session.load(Users.class, userId);
    Users user = (Users)session.get(Users.class, userId);
    区别:
    - 如果数据库中没有userId对象:
        - get()返回的是null
        - load()返回一个代理对象,调用对象的某个方法会抛出异常。
    - load支持延迟加载,get不支持延迟加载
4. Hibernate中Java对象的状态有哪些?
    - 临时状态
    - 持久化状态
    - 游离状态
5. Session的清理和清空有什么区别?
6. Hibernate如果进行大批量操作?
7. 如何调用原生 SQL?
8. Hibernate中getCurrentSession()和openSession()的区别?
9. Hibernate的优缺点?

MyBatis

1. Hibernate和MyBatis的最大区别?
    - 1. Hibernate是全自动的,Mybaits是半自动的
    - 2. 移植性。
    - 3. 日志系统。
    - 4. SQL优化上。Mybatis比Hibernate强。
    - 5. 缓存。Hibernate比Mybaits缓存强,Hibernate有二级缓存,支持第三方缓存。

分布式

1. zookeeper用途
2. dubbo的用途与优点
3. dubbo的设计思路
    0. 服务器启动,加载,运行服务提供者。
    1. 服务提供者启动时,向注册中心注册自己提供的服务。
    2. 服务消费者启动时,向注册中心订阅自己所需的服务。
    3. 注册中心向服务消费者返回服务提供者的地址列表。如果有变更,注册中心将基于长连接推送变更数据给服务消费者。
    4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用。如果调用失败,再选一台。
    5. 服务提供者和消费者,在内存中统计调用次数和调用时间,定时每分钟将统计数据发送到监控。
    
--------------------------
|                       
|                   Zookeeper
|           [2]                  [1]
|           ----->             <-----
|           <-----
|           [3]         [4]
|Consumer           -------->           Provider
|                                       Container[0]
|           ------>             <-----    
|           [5]                 [5]
|                   Moniter
 --------------------------

4.dubbo连接注册中心和直连的区别?
    在开发和测试环境下,经常需要绕过注册中心,只测试指定的服务提供者,这个时候需要点对点直连。
    服务注册中心,动态的注册和发现服务,使服务的位置透明,并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover, 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 
    服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外,注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者。 
    注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表 
    注册中心和监控中心都是可选的,服务消费者可以直连服务提供者。
            

5.dubbo在安全机制方面是如何解决的?
    - dubbo通过`令牌`防止用户绕过注册中心直连,然后再注册中心管理授权。
        还通过黑白名单的方式,来控制服务所允许的调用方。

6.dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,发布者和订阅者之间还能通信么?
    - 可以的,启动dubbo时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用.

缓存

缓存的使用场景
缓存命中率的计算
Memcache与Redis的比较
如何实现Redis的分片
MongoDB的特点
Redis如何解决key冲突

其他

1. [美团]读过哪些源码,最近在看什么书
2. [美团]实习过程中的任务、技术点
3. [美团]实现公司的管理方式
4. [美团]实现过程最大的收获
5. 大型网站在架构上应该考虑哪些问题?
    - 分层:处理复杂系统最常用的手段之一。
    - 分割:按功能进行横向分割。
    - 分布式:静态资源单独服务器处理。
    - 集群
    - 缓存:空间换时间。
    - 异步:使用消息队列将调用异步化,起到削峰作用。
6. 你用过的网站前端优化技术有哪些?
    - 1. 浏览器访问优化
        - 减少HTTP请求
        - 使用浏览器缓存
    - 2. CDN加速:
        - 将数据缓存在离用户最近的机房
    - 3. 反向代理
        - 相当于应用服务器的门面,可以保护网站的安全性,也可以实现负载均衡。

7. 什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?
    - XSS:跨站点脚本攻击。在网页中注入恶意脚本。
        - 类型:
            1. 反射型攻击。诱使用户点击恶意链接。
            2. 持久型攻击。将恶意脚本提交到被攻击网站的数据库中。
        - 防范:
            1. 对危险字符进行转义。
    - SQL注入:
            将恶意的SQL被嵌入到SQL中交给数据库执行。
        - 防范:
            1. 通过正则对请求参数进行验证。
            2. 参数绑定。PreparedStatement。
    - CSRF:跨站点请求伪造。
        http://blog.csdn.net/stpeace/article/details/53512283
        - 防范:
            1. 验证HTTP Refer字段。
            2. 在请求地址中添加Token并验证。
            3. 在HTTP请求中添加自定义属性并验证。

对象头Mark
描述对象的Hash、锁信息、垃圾回收标记、年龄等信息。
1. 偏向锁
    为什么?大部分情况是没有竞争的,所以通过偏向来提高性能。
    偏向?就是锁会偏向于已经占有锁的线程;
    原理?通过对象头Mark的标记设置为偏向,并将线程ID写入对象头Mark。
        - 只有没有竞争,获取偏向锁的线程,在将来进入同步块,不需要做同步。
        - 当其他线程请求相同锁时,偏向模式结束>
    使用?-XX:+UseBiasedLocking(默认启用)
        -XX:-UseBiasedLocking
    坏处?在竞争激烈的场合,偏向锁会增加系统负担。
    好处?提高5%的性能。

2. 轻量锁  
    普通锁处理性能不够理想,轻量锁是一种快速的锁定方法.
    BasicLockObject
    嵌入在`线程栈`中的对象
    如果对象没有锁定:
        - 对象的Mark指针保存在锁对象中。
        - 将对象头设置为指向锁的指针。
    如果轻量锁失败,表示存在竞争,升级为重量级锁。
        - 在没有锁竞争添加下,减少传统锁的使用OS呼出量产生的性能损耗。
        - 在竞争激烈时,轻量锁会多做很多额外的操作,导致性能下降。
    
3. 自旋锁
    `在存在竞争的时候`,如果线程可以很快获得锁,让线程做几个空循环。
    jdk1.6中:-XX:+UseSpinning
    jdk1.7中去掉此参数,改为默认实现。
    如果同步块很长,自旋失败,会降低系统性能。
    如果同步块很短,自旋成功,节省线程挂起时间,提升性能。

总结:
    - 不是Java语言层面的锁优化方法。
    - 内置于JVM中的获取锁的优化方法。
        - 偏向锁可用,先尝试获取偏向锁
        - 轻量级锁可用,先尝试轻量级锁
        - 以上都失败,尝试自旋锁
        - 在失败,再尝试普通锁,使用OS互斥量在操作系统层面挂起


锁优化:
1. 减少锁的持有时间
2. 减少锁粒度
    - 大对象拆成小对象,大大增加并行度,降低锁竞争
    - 偏向锁、轻量级锁成功率提高
    - ConcurrentHashMap
        - 如果干Segment:Segment[] segment
        - Segment中维护HashEntry
        - 允许多个线程进入
3. 锁分离
    - ReadWriteLock
    - LinkedBlockingQueue
4. 锁粗化
5. 锁消除
    在即使编译器时,如果发现不可能被共享的对象,则可以消除这些对象的锁操作。
    for(int i=0;i<10000;i++){
        StringBuffer sb = new StringBuffer();//同步操作
        sb.append("1");
    }
6. 无锁
    CAS:CompareAndSwap

税友

1. GC算法
2. java8为什么不兼容java7?
3. java8比java7优化在哪?
4. 并行和并发的区别?

    /**
     * 二分查找[非递归实现]
     *
     * @param array
     * @param target
     * @return 返回出现在数组中的位置
     */
    public static int binSearch(int[] array, int target) {
        int low  = 0;
        int high = array.length - 1;
        int mid;
        while (low <= high) {
            mid = (low + high) / 2;

            if (array[mid] == target) {
                return mid + 1;
            } else if (array[mid] < target) {
                low = mid + 1;
            } else if (array[mid] > target) {
                high = mid - 1;
            }
        }

        return -1;
    }

    /**
     * 二分查找[递归实现]
     * 时间复杂度O(logN)
     *
     * @param array
     * @param target
     * @return
     */
    public static int binSearch2(int[] array, int target, int low, int high) {
        if (low <= high) {
            int mid = (low + high) / 2;
            if (array[mid] == target) {
                return mid + 1;
            } else if (array[mid] < target) {
                return binSearch2(array, target, mid + 1, high);
            } else {
                return binSearch2(array, target, low, mid - 1);
            }
        }

        return -1;
    }

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