异常处理机制主要回答了三个问题
Java的异常体系
从概念角度解析Java的异常处理机制
从责任角度看:
常见的Error以及Exception
RuntimeException
非 RuntimeException
Error
NoclassDefFoundError的成因
Java异常的处理原则
高效主流的异常处理框架
在用户看来,应用系统发生的所有异常都是应用系统內部的异常
Java异常处理消耗性能的地方
尽量少的try-catch代码行,只包住有异常的代码。
不要利用try-catch,控制业务的流程。
数据结构考点
算法考点
考点扩展:
compare和自定义的compare
HashMap、HashTable、ConccurentHashMap的区别?
HashMap:(Java8以前):数组+链表,非synchronized,速度快。
(Java8后):数组+链表+红黑树
某个桶上高于8,则转为红黑树,小于6则转为链表。
HashMap在使用的时候,才会被初始化。
首次使用才会创建(延迟加载策略)
HashMap中的put方法逻辑:
计算HashCode方法
扩容resize()
负载因子
transient Node<K,V>[] table;
达到0.75以后,扩大为原来2倍。
树(Node
static final int TREEIFY_THRESHOLD = 8;(树转化为红黑树)
HashMap:扩容的问题
HashMap知识点
互斥Object对象mutex,使用synchronized对mutex进行加锁。
HashTable,给public方法进行加锁、
HashMap进行,线程安全操作
互斥Object对象mutex,使用synchronized对mutex进行加锁。
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class test001 {
public static void main(String[] args) {
// 创建HashMap
HashMap hashMap = new HashMap<>();
// 将HashMap(不安全)转为线程安全的
Map safeHashMap = Collections.synchronizedMap(hashMap);
safeHashMap.put("aa","1");
safeHashMap.put("bb","2");
System.out.println(safeHashMap.get("bb"));
}
}
HashTable,给public方法进行加锁、
线性执行,效率低(HashTable、HashMap)
ConcurrentHashMap的使用(JUC包java.util.cuncurrent)
早期的 ConcurrentHashMap:通过分段锁 Segmen来实现
当前 ConcurrentHashMap:CAS+ synchronized使锁更细化
数据结构进行优化:数组+链表+红黑树
synchronized只锁定链表和红黑树的首节点。
大小控制标识符,Hash初始化,扩容表示
private transient volatile int sizeCtl;
-1:正在进行初始化。
负数:正在进行初始化或扩容操作。
-n:有n个线程正在进行初始化或扩容操作。
正数/0:Hash表还未被初始化
ConcurrentHashMap总结:比Segment(分段锁),锁拆的更细。
ConcurrentHashMap:别的需要注意的点
Hash Map、 Hashtable、 ConccurentHashMap三者区别
java.util.concurrent:提供了并发编程的解决方案
JUC包的分类
并发工具类(tools)
闭锁(CountDownLatch):让主线程等待一组事件发生后继续执行
栅栏(CyclicBarrier):阻塞当前线程,等待其他线程
信号量(Semaphore):控制某个资源可被同时访问的线程个数
交换器(Exchanger):两个线程到达同步点后,相互交换数据。
数据进行了交换:
Blocking Queue:提供可阻塞的入队和出队操作
尾插,成功true,失败抛异常
boolean add(E e);
尾插,满了则阻塞,直到添加成功
void put(E e) throws InterruptedException;
尾插,成功true,失败fal se
boolean offer (E e);
尾插,等待timeout时间添加数据
boolean offer(E e,long timeout,TimeUnit unit)throws InterruptedException;
从头获取数据,为空,则一直等待有元素再返回。
take(E e )throws InterruptedException;
从头部取数据,等待一段时间获取数据
poll(long timeout,TimeUnit unit)throws InterruptedException;
Blocking Queue
主要用于生产者-消费者模式,在多线程场景时生产者线程在队列尾部添加元素,而消费者线程则在队列头部消费元素,通过这种方式能够达到将任务的生产和消费进行隔离的目的
10、Java的I/O机制
BIO、NIO、AIO区别
BIO:Block-I0: InputStream和outputStream, Reader和Writer
IO执行的阶段,线程是被阻塞的。
NIO:Non Block-Io:构建多路复用的、同步非阻塞的IO操作
NIO的核心
Channels的下级分类
transferTo:把 Filechannel中的数据拷贝到另外一个 Channel
transfer From:把另外一个 Channe中的数据拷贝到 Filechannel
避免了两次用户态和内核态间的上下文切换,即”零拷贝”,效率较高
Buffers(缓冲)
Selectors( 选择器)
IO多路复用:调用系统级别的 select、poll、epoll
select、poll,epol的区别
支持一个进程所能打开的最大连接数
select | 单个进程所能打开的最大连接数由FD_SETSIZE宏定义,其大小是32个整数的大小(在32位的机器上,大小是3232,64位机器上FD (SETSIZE为3264),我们可以对其进行修改,然后重新编译內核,但是性能无法保证,需要做进一步测试 |
---|---|
poll | 本质上与select没有区别,但是它没有最大连接数的限制,原因是它是基于链表来存储的 |
epoll | 虽然连接数有上限,但是很大,1G内存的机器上可以打开10万左右的连接 |
FD(文件句柄)剧增后带来的IO效率问题
select | 因为每次调用时都会对连接进行线性遍历,所以随着FD的增加会造成遍历速度的"线性下降"的性能问题 |
---|---|
poll | 同上 |
epoll | 由于epoll是根据每个FD上的 callback函数来实现的,只有活跃的 socket才会主动调用 callback,所以在活跃 socket较少的情况下,使用epoll不会有"线性下降"的性能问题,但是所有 socket都很活跃的情况下,可能会有性能问题 |
消息传递方式
select | 内核需要将消息传递到用户空间,需要內核的拷贝动作 |
---|---|
poll | 同上 |
epoll | 通过内核和用户空间共享一块内存来实现,性能较高 |
AIO异步IO(Asynchronous IO:基于事件和回调机制)
AIO如何进一步加工处理结果
BO、NIO、AIO对比
属性\模型 | 阻塞BIO | 非阻塞NIO | 异步AIO |
---|---|---|---|
blocking | 阻塞并同步 | 非阻塞但同步 | 非阻塞并异步 |
线程数(server:client) | 1:1 | 1:N | 0:N |
复杂度 | 简单 | 较复杂 | 复杂 |
吞吐量 | 低 | 高 | 高 |