文章目录
java异常体系
Error和Exception的区别
- Error:程序无法处理的系统错误,编译器不做检查。是系统致命错误,程序无法处理的,一般指与jvm相关的错误,如:栈溢出、系统崩溃、虚拟机错误等。
1.NoClassDefFoundError -找不到class定义的异常
2.StackOverflowError -深递归导致栈被耗尽而抛出的异常
3.OutOfMemoryError -内存溢出异常
- Exception:程序可以处理的异常,铺货后可能恢复。遇见这样的问题,应该尽可能处理,使程序恢复正确。
RuntimeException与CheckedException
总结:前者是程序无法处理的错误,后者是可以处理的异常。
- RuntimeException:是不可预知的,程序应当自行避免。
1.NullPointerException -空指针引用异常
2.ClassCastException -类型强制转换异常
3.IlegalArgumentException -传递非法参数异常
4.IndexOutOfBoundsException -下标越界异常.
5.NumberFormatException -数字格式异常
- 非RuntimeException:可预知的,从编译器校验的异常,不处理是无法通过编译的。
1.ClassNotFoundException -找不到指定class的异常
2.IOException - IO操作异常
从责任角度看:
- Error属于JVM需要负担的责任;
- RuntimeException是程序应该负担的责任;
- Checked Exception可检查异常是Java编译器应该负担的责任。
处理机制
➢抛出异常:创建异常对象,交由运行时系统处理
➢捕获异常:寻找合适的异常处理器处理异常,否则终止运 行
具体明确
:抛出的异常应能通过异常类名和message准确说明异常的类型和产生异常的原因;
提早抛出
:应尽可能早的发现并抛出异常,便于精确定位问题;
延迟捕获
:异常的捕获和处理应尽可能延迟,让掌握更多信息的作用域来处理异常。
Java异常处理消耗性能的地方
➢try-catch块影 响JVM的优化
➢异常对象实例需要保存栈快照等信息,开销较大,建议不要使用try-catch来控制程序流程。
java集合框架
➢HashMap线程不安全,数组+链表+红黑树
➢Hashtable线程安全 ,锁住整个对象,数组+链表
➢ConccurentHashMap线程安全, CAS+同步锁,数组+链表+红黑树
➢HashMap的key、value均可为null ,而其他的两个类不支持
HashMap : put方法的逻辑
1、如果HashMap未被初始化过,则初始化
2、对Key求Hash值,然后再计算下标
3、如果没有碰撞,直接放入桶中
4、如果碰撞了,以链表的方式链接到后面
5、如果链表长度超过阀值,就把链表转成红黑树
6、如果链表长度低于6 ,就把红黑树转回链表
7、如果节点已经存在就替换旧值
8、如果桶满了(容量16*加载因子0.75) ,就需要resize (扩容2倍后重排)
ConcurrentHashMap : put方法的逻辑
1.判断Node[数组是否初始化 ,没有则进行初始化操作
2.通过hash定位数组的索引坐标 ,是否有Node节点,如果没有则使用CAS进行添加(链表的头节点) , 添加失败则进入下次循环。
3.检查到内部正在扩容,就帮助它-块扩容。
4.如果f!=null ,则使用synchronized锁住f元素(链表/红黑二.叉树的
头元素)。如果是Node(链表结构)则执行链表的添加操作;如果是TreeNode(树型结构)则执行树添加操作。
5.判断链表长度已经达到临界值8 ,当然这个8是默认值,大家也可以去做调整,当节点数超过这个值就需要把链表转换为树结构。
J.U.C
在这里插入图片描述
java.util.concurrent :提供了并发编程的解决方案
➢CAS是java.util.concurrent.atomic包的基础
➢AQS是java.util.concurrent.locks包以及一 -些常用类比如Semophore , ReentrantLock等类的基础
J.U.C包的分类
➢线程执行器executor
➢锁locks
➢原子变量类atomic
➢并发工具类tools
➢并发集合collections
(待后续更新)
io机制
BIO、NIO、 AIO
Block-IO
: InputStream和OutputStream , Reader和Writer
基于流模型实现,交互方式是同步阻塞,在读取输入流和写入输出流的时候在读写操作完成之前,线程会一直阻塞在那里,他们的调用是可靠的线性顺序。
程序发送请求给内核,由内核进行通信,在内核准备好数据之前,线程是被挂起的,所以在这两个阶段程序都是被挂起的状态。类比client-server模式,则其实现模式为一个连接对应一个线程,即客户端有连接请求时,服务端就需要启动一个线程进行处理,等待操作系统返回结果,如果这个链接不做任何事情,会造成不必要的线程开销(当然可以采用线程池来改善)。BIO的特点就是在IO执行的两个阶段都被阻塞住。
特点:代码简单、直观、效率和拓展性存在瓶颈。
NonBlock-IO
:构建多路复用的、同步非阻塞的IO操作
java4引入了NIO,当线程发起第一次请求,线程并没有被阻塞,而是反复的去检查(检查时会有阻塞,类似自旋)数据是否准备好,把原来大块的不能用的阻塞时间分解成小的阻塞,所以线程会不断的有机会去执行。
这个检查有没有准备好数据的过程,类似于“轮询”。类比client-server模式,一个请求对应一个线程,即客户端发送的连接请求都会被注册到“多路复用器”上,“多路复用器”轮询到连接有io请求时才启动一个线程进行处理。
NIO的特点就是:程序需要不断的去询问内核是否已经准备好数据,在“反复查看数据”的过程是非阻塞的,在“拷贝数据”的过程是阻塞的。
NIO核心:
IO的多路复用:调用系统级别的select\poll\epoll
单线程可以同时处理多个网络io,调用系统级别的select、poll、epoll模型,由系统监控io状态。其中select、poll、epoll支持的一个进程所能打开的最大连接数如图。
Asynchronous IO
:基于事件和回调机制
异步非阻塞IO方式,基于事件和回调机制,简单理解为应用操作直接返回不会阻塞,当后台操作完成,操作系统就会通知响应线程进行后续工作。
AIO通过下面方式处理加工结果:
- 基于回调:实现CompletionHandler接口,调用时触发回调函数
- 返回Future:通过isDone()查看是否准备好,通过get()等待返回数据