String,StringBuffer,SrtingBuilder的区别java
目录 面试
java异常
异常处理机制主要回答了三个问题算法
- what:异常类型回答了什么被抛出
- where:异常堆栈跟踪回答了在哪抛出
- why:异常信息回答了为何抛出
Java的异常体系

RuntimeException:不可预知的,程序应当自行避免编程
- NullpointException——空指针异常
- ClassCastException——类型强制转换异常
- IllegalArragumentException——传递非法参数异常
- IndexOutOfBoundsException——下标越界异常
- NumberFormatException——数字格式异常
非RuntimeException:可预知的,从编译器校验的异常数组
- ClassNotFoundException——找不到指定的class的异常
- IOException——IO操做异常
Error安全
- NoClassDefFoundError——找不到class定义的异常
- StackOverflowError——深递归致使栈被耗尽而抛出的异常
- OutOfMemoryError——内存溢出异常
NoClassDefFoundError的成因:数据结构
- 类依赖的class或者jar不存在
- 类文件存在,可是存在不一样的域中
- 大小写问题,javac编译的时候是无视大小写的,颇有可能编译出来的class文件就与想要的不同
从责任角度看:多线程
- Error属于JVM须要负担的责任
- RuntimeException是程序应该承担的责任
- Check Exception可检查异常是Java编译器应该负担的责任
Error和Exception的区别
从概念角度解析Java的异常处理机制并发
- Error:程序没法处理的系统错误,编译器不检查
- Exception:程序能够处理的异常,捕获后可能恢复
- 总结:前者是程序没法处理的错误,后者是能够处理的异常
Java的异常处理机制
抛出异常:建立异常对象,交由运行时系统处理app
在用户看来,应用系统发生的全部异常都是应用系统内部的异常
- 设计一个通用的继承自RuntimeException的异常来同一处理
- 其他异常都统一译为上述异常AppException
- 在catch以后,抛出上述异常的子类,并提供足以定位的信息
Java异常处理消耗性能的地方
- try-catch块印象概念股JVM的优化
- 异常对象实例须要保存栈快照等信息,开销较大
Java集合框架
工做中消失而面试却长存的算法与数据结构
数据结构考点
- 数组和链表的区别
- 链表的操做,如反转,链表环路检测,双向链表,循环链表相关操做
- 队列,栈的应用
- 二叉树的遍历方式及其递归和非递归的实现
- 红黑树的旋转
算法考点
- 内部排序:如递归排序、交换排序(冒泡、快排)、选择排序、插入排序
- 外部排序:应掌握如何利用有限的内存配合海量的外部存储来处理超大的数据集,写不出也要有相关的思路

HashMap、HashTable、ConccurentHashMap
HashMap(Java8之前):数组+链表
hash(key.hashCode())%len

HashMap(Java8及之后):数组+链表+红黑树
性能从O(n)提升到O(logn)

如何优化Hashtable?
早期的ConcurrentHashMap:经过分段锁Segment来实现
数据+链表

ConcurrentHashMap
当前的ConcurrentHashMap:CAS+synchronized使锁更细化
数组+链表+红黑树

ConcurrentHashMap:put方法的逻辑
- 判断Node[]数组是否初始化,没有则进行初始化操做
- 经过hash定位数组的索引坐标,是否有Node节点,若是没有则使用CAS进行添加(链表的头结点),添加失败则进入下次循环
- 检查到内部正在扩容,就帮助它一块扩容
- 若是f!=null,则使用synchronized锁住f元素(链表/红黑二叉树的头元素)
- 若是是Node(链表结构)则执行链表ode添加操做
- 若是是TreeNode(树形结构)则执行树添加操做
- 判断链表长度已经达到临界值,固然这个8是默认值,你们也能够去作调整,当节点数超过这个值就须要把链表转换为树结构
ConcurrentHashMap总结:比起Segment,锁拆的更细
- 首先使用无锁操做CAS插入头结点,失败则循环重试
- 若头结点已存在,则尝试获取头结点的同步锁,再进行操做
ConcurrentHashMap:注意
- size()和mappingCount()的一桶,二者计算是否准确
- 多线程环境下如何进行扩容
三者的区别
- HashMap线程不安全,数组+链表+红黑树
- Hashtable线程安全,锁住整个对象,数组+链表
- ConcurrentHashMap线程安全,CAS+同步锁,数组+链表+红黑树
- HashMap的key、value都可为null,而其余的两个类不支持
Java.util.concurrent:提供了并发编程的解决方案
- CAS是java.util.concurrent.atomic包的基础
- AQS是java.util.concurrent.locks包以及一些经常使用类好比Semophore,ReentrantLock等类的基础
J.U.C包的分类
- 线程执行器executor
- 锁locks
- 原子变量类atomic
- 并发工具类tools
- 并发集合collections
CountDownLatch:让主线程等待一组时间后继续执行
- 事件指的是CountDownLatch里的countDown()

CyclicBarrier:阻塞当前线程,等待其余线程
- 等待其余线程,且会阻塞本身当前线程,全部线程必须同时到达栅栏位置后,才能继续执行
- 全部线程到达栅栏处,能够触发执行另外一个预先设置的线程

Semaphore:控制某个资源可被同时访问的线程个数

BlockingQueue:提供可阻塞的入队和出队操做
主要用于生产者-消费者模式,在多线程场景时生产者线程在队列尾部添加元素,而消费者线程则在队列头部消费元素,经过这种方式可以到达将任务的生产和消费进行隔离的目的
- ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列
- LinkedBlockingQueue:一个由链表结构组成的有界/无界阻塞队列
- PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列
- DealyQueue:一个使用优先级队列实现的无界阻塞队列
- SynchronousQueue:一个不存储元素的阻塞队列
- LinkedTransferQueue:一个由链表结构哦组成的无界阻塞队列
- LinkedBlockingQueue:一个由链表结构组成的双向阻塞队列

Java的IO机制
BIO、NIO、AIO

Block-IO:InputStream和OutputStream,Reader和Writer

NonBlock-IO:构建多路复用的、同步非阻塞的IO操做

NIO的核心
- Channels
- FileChannel
- transferTo:把FileChannel中的数据拷贝到另外一个Channel
- transferFrom:把另外一个Channel中的数据拷贝到FileChannel避免了两次用户态巨额内核态间的上下文切换,即“零拷贝”,效率较高
- DatagramChannel
- SocketChannel
- ServerSocketChannel
- Buufers
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
- MappedByteBuffer
- Seletors


select、poll、epoll的区别
支持一个进程所能打开的最大链接数

FD剧增后带来的IO效率问题

Asynchronus IO:基于时间和回到机制

AIO如何进一步加工处理结果
- 基于回调:实现ComplerionHandlerj接口,调用时触发回调函数
- 返回Future:经过isDone()查看是否准备好,经过get()等待返回数据