[面试] 面试题
标签(空格分隔): 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三次握手、四次挥手,为什么建立连接是三次,断开连接是四次?
- 为什么握手不是两次?
为了因为网络延迟而导致的重复链接。
- 为什么断开是四次?
因为服务端需要把未传输完的数据传输完。
2. [美团]HTTP POST和GET的区别和联系。
3. HTTPS的传输过程
- 怎么实现通信安全?
HTTPS是用SSL、TLS协议来实现信息安全的。
- Https是哪一层的协议?
应用层
- Http原来和TCP直接通信,加入SSL后,HTTP先和SSL通信,再由SSL和TCP通信。
- SSL使用的是非对称加密算法。
- HTTPS缺点:
加解密比较耗时。
- HTTPS是为了预防`中间人攻击`。
- HTTP+加密+认证+完整性=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
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地址.
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;
}