Java 常用类库与技巧【笔记】
Java 常用类库与技巧【笔记】
Java异常体系
Java异常相关知识
Java在其创立的时候就设置了比较有效的处理机制,其异常处理机制主要回答了三个问题:what,where,why
what表示异常类型回答了什么被抛出
where表示异常堆栈跟踪回答了在哪儿抛出
why表示异常信息回答了为什么被抛出
error和exception的区别
Java异常体系
runtimeexception是不可预知的,程序应当自行避免,而非runtimeexception是可以预知的,从编译器中校验异常
从责任的角度来看:
1.Error属于JVM需要负担的责任
2.RuntimeException是程序应该负担的责任
3.Checked Exception可检查异常是Java编译器应该负担的责任
从概念角度解析Java的异常处理机制
error是程序无法处理的系统错误,编译器不做检查,而exception则是程序可以处理的异常,在捕获之后可能恢复,也就是说,error是程序无法处理的错误,而exception则是可以处理的异常
常见的error和exception
RuntimeException中有五个比较常见的异常
1.NullPointerException -空指针引用异常
2.ClassCastException -类型强制转换异常
3.IllegalArgumentException -传递非法参数异常
4.IndexOutOfBoundsException -下标越界异常
5.NumberFormatException -数字格式异常
非runtimeexception的常见异常
1.ClassNotFoundException -找不到指定class的异常
2.IOException - IO操作异常
Error的常见异常
1.NoClassDefFoundError -找不到class定义的异常
NoClassDefFoundError的成因:1.类依赖的class或者jar不存在,2.类文件存在,但是存在不同的域中,3.大小写问题,javac编译的时候是无视大小写的,很有可能编译出来的class文件就与想要的不一样
2.StackOverflowError -深递归导致栈被耗尽而抛出的异常
3.OutOfMemoryError -内存溢出异常
Java的异常处理机制
抛出异常:创建异常对象,交由运行时系统处理
捕获异常:寻找合适的异常处理器处理异常,否则就会终止运行
具体明确︰抛出的异常应能通过异常类名和message准确说明异常的类型和产生异常的原因
提早抛出:应尽可能早的发现并抛出异常,便于精确定位问题
延迟捕获︰异常的捕获和处理应尽可能延迟,让掌握更多信息的作用域来处理异常
高效主流的异常处理框架
在用户看来,应用系统发生的所有异常都是应用系统内部的异常,那么就可以设计一个高效主流的异常处理框架
设计一个通用的继承自RuntimeException异常来统一处理,而其余异常都统一转译为上述异常AppException,然后进行转换,在catch之后,抛出上述异常的子类,并提供足以定位的信息,这样在异常发生的时候,就可以由前端接受AppException做统一处理
try-catch的性能
Java异常处理消耗性能的地方
try-catch块影响JVM的优化
异常对象实例需要保存栈快照等信息,开销较大
Java集合框架
集合之list和set
集合之Map
hashmap,hashtable,conccurenthashmap的区别
hashmap
hashmap在Java8以前是数组+链表的组合,容易性能恶化
所以在Java8以及以后,变成了数组+链表+红黑树的结构
hashmap的put方法的逻辑:
1、如果HashMap未被初始化过,则初始化
2、对Key求Hash值,然后再计算下标
3、如果没有碰撞,直接放入桶中
4、如果碰撞了,以链表的方式链接到后面
5、如果链表长度超过阀值,就把链表转成红黑树
6、如果链表长度低于6,就把红黑树转回链表
7、如果节点已经存在就替换旧值
8、如果桶满了(容量16*加载因子0.75),就需要resize (扩容2倍后重排)
hashmap如何有效的减少碰撞
可以使用扰动函数(促使元素位置分布均匀,减少碰撞机率)或者使用final对象,并采用合适的equals()和hashCode()方法
hashmap中获取hash到散列的过程
hashmap的扩容问题
在多线程的环境下,调整大小会存在条件竞争,容易造成死锁,而且在扩容过程中的重新填入的过程rehashing是个很耗时的过程
Hashtable和concurenthashmap
知道了hashmap 以后,相应的hashtable也很容易理解
如何优化hashtable?
可以通过锁的细粒度化,将整个锁拆解成多个锁进行优化,早期的concurenthashmap就是这样做的,通过分段锁segment来实现
此时发现,可以将分段锁拆的更细,或者说,不用分段锁,使每一个table都带一把锁,于是就有了当前的concurrenthashmap,使用CAS和synchronized结合使锁更细化
concurenthashmap的put方法的逻辑
1.判断Node[]数组是否初始化,没有则进行初始化操作
2.通过hash定位数组的索引坐标,是否有Node节点,如果没有则使用CAS进行添加(链表的头节点),添加失败则进入下次循环
3.检查到内部正在扩容,就帮助它一块扩容
4.如果f!=null,则使用synchronized锁住f元素(链表/红黑二叉树的头元素),如果是Node(链表结构)则执行链表的添加操作,如果是TreeNode(树型结构)则执行树添加操作
5.判断链表长度已经达到临界值8,当然这个8是默认值,大家也可以去做调整,当节点数超过这个值就需要把链表转换为树结构
concurenthashmap的总结
对于concurrenthashmap,总的来说就是比起segment,锁拆的更细,只要hash不冲突,就不会出现并发获得锁的情况
首先使用无锁操作CAS插入头节点,失败则循环重试
若头节点已存在,则尝试获取头节点的同步锁,再进行操作
hashmap,hashtable,conccurenthashmap三者的区别总结
HashMap线程不安全,数组+链表+红黑树
Hashtable线程安全,锁住整个对象,数组+链表
ConccurentHashMap线程安全,CAS+同步锁,数组+链表+红黑树
HashMap的key、value均可为null,而其他的两个类不支持
J.U.C知识点梳理
J.U.C包(java.util.concurrent)中的核心
CAS是java.util.concurrent.atomic包的基础
AQS是java.util.concurrent.locks包以及一些常用类比如Semophore , ReentrantLock等类的基础
J.U.C包的分类
1.线程执行器executor
2.锁locks
3.原子变量类atomic
4.并发工具类tools
5.并发集合collections
并发工具类
四个同步器
闭锁CountDownLatch,让主线程等待一组事件发生后继续执行,这里的事件指的是countdownlatch里的countdown()方法
栅栏CyclicBarrier,作用是阻塞当前的进程,等待其他的进程,等待其它线程,且会阻塞自己当前线程,所有线程必须同时到达栅栏位置后,才能继续执行,而且所有线程到达栅栏处,可以触发执行另外一个预先设置的线程
信号量Semaphore,控制某个资源可被同时访问的线程个数
交换器Exchanger,当两个线程到达同步点后,相互交换数据
Blockingqueue
这是提供可阻塞的入队和出队操作,主要用于生产者-消费者模式,在多线程场景时生产者线程在队列尾部添加元素,而消费者线程则在队列头部消费元素,通过这种方式能够达到将任务的生产和消费进行隔离的目的
Blockingqueue的七个队列实现
1、ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列
2、LinkedBlockingQueue :一个由链表结构组成的有界/无界阻塞队列
3、PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列
4、DealyQueue :一个使用优先级队列实现的无界阻塞队列
5、SynchronousQueue : 一个不存储元素的阻塞队列
6、LinkedTransferQueue :一个由链表结构组成的无界阻塞队列
7、LinkedBlockingDeque :一个由链表结构组成的双向阻塞队列
Java的I/O机制
BIO,NIO,AIO的区别
Block-IO(BIO)
有InputStream和OutputStream , Reader和Writer,是基于流模型实现的,这就意味着其交互方式是同步阻塞的方式
NonBlock-IO(NIO)
构建多路复用的、同步非阻塞的IO操作
其核心部分为,Channels,Buffers,Selectors
NIO-Channels的种类
FileChannel
transferTo:把FileChannel中的数据拷贝到另外一个Channel
transferFrom :把另外一个Channel中的数据拷贝到FileChannel
这个接口常常用于高效的网络文件的传输和大文件拷贝,其避免了两次用户态和内核态之间的上下文切换,即零拷贝,效率很高
DatagramChannel
SocketChannel
ServerSocketChannel
NIO-Buffers的种类
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
MappedByteBuffer
NIO-Selector
其允许单线程处理多个channel,如果一个应用打开了多个链接,每个链接的流量都很低,那么使用这个就很方便
I/O多路复用
可以调用系统级别的select,poll以及epoll
select,poll以及epoll三者的区别
可以三个方面来说
1.支持一个进程能打开的最大的连接数
select:单个进程所能打开的最大连接数由FD_SETSIZE宏定义,其大小是32个整数的大小(在32位的机器上,大小是3232,64位机器上FD_SETSIZE为3264 ),我们可以对其进行修改,然后重新编译内核,但是性能无法保证,需要做进—步测试
poll:本质上与select没有区别,但是它没有最大连接数的限制,原因是它是基于链表来存储的
epoll:虽然连接数有上限,但是很大,1G内存的机器上可以打开10万左右的连接
2.FD剧增后带来的IO效率问题
select:因为每次调用时都会对连接进行线性遍历,所以随着FD的增加会造成遍历速度的"线性下降"的性能问题
poll:和select一样
epoll:由于epoll是根据每个fd上的callback函数来实现的,只有活跃的socket才会主动调用callback ,所以在活跃socket较少的情况下,使用epoll不会有"线性下降"的性能问题,但是所有socket都很活跃的情况下,可能会有性能问题
3.消息的传递方式
select:内核需要将消息传递到用户空间,需要内核的拷贝动作
poll:和select一样
epoll:通过内核和用户空间共享一块内存来实现,性能较高
Asynchronous IO(AIO)
基于事件和回调机制
AIO进一步加工数据结果方法
基于回调:实现CompletionHandler接口,调用时触发回调函数
返回Future:通过isDone()查看是否准备好,通过get()等待返回数据
BIO,NIO,AIO的对比总结
Java 常用类库与技巧【笔记】的更多相关文章
- Java常用类库与技巧
Java异常 异常处理机制主要回答了三个问题 What:异常类型回答了什么被抛出 Where:异常堆栈跟踪回答了在哪抛出 Why:异常信息回答了为什么被抛出 Java的异常体系
- Google的Java常用类库 Guava资料
java的人应该都知道Apache commons的java常用类库吧,这个Guava和commons一样,封装出一套比jdk本身提供的常用类库强大.既然有了这个这么强大的类库,我们就没必要重复造轮子 ...
- JAVA(三)JAVA常用类库/JAVA IO
成鹏致远 | lcw.cnblog.com |2014-02-01 JAVA常用类库 1.StringBuffer StringBuffer是使用缓冲区的,本身也是操作字符串的,但是与String类不 ...
- 菜鸡的Java笔记 - java 常用类库
CommonClassLibrary 常用类库 定时调度 定时调度指的是每到一个时刻,都会自动的产生某些特定的操作形式 con ...
- JAVA常用类库简介(转)
Java编程语言中为方便学习者学习,编制了许多类,这些类已经经过测试,都是我们编程的基础.如果不利用这些已存在的类,我们的编程工作将变得异常复杂并且效率低下.所以我们应尽可能多的掌握Java基本类库的 ...
- Java常用类库API之MD5简单使用
常用类库--MD5简单使用 MD5消息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash v ...
- Java常用类库2
1.java.util.Date类 package LESSON9; import java.util.Date; public class demo1 { public static void ma ...
- 谈谈Java常用类库中的设计模式 - Part Ⅰ
背景 最近一口气看完了Joshua Bloch大神的Effective Java(下文简称EJ).书中以tips的形式罗列了Java开发中的最佳实践,每个tip都将其意图和要点压缩在了标题里,这种做法 ...
- Java常用类库 读书笔记 二
1.Date类 常用操作方法: public Date () 构造方法,实例化Date类对象 public Data(long Date) ...
随机推荐
- Pandas高级教程之:GroupBy用法
Pandas高级教程之:GroupBy用法 目录 简介 分割数据 多index get_group dropna groups属性 index的层级 group的遍历 聚合操作 通用聚合方法 同时使用 ...
- Centos6.7 minimal安装GitLab8.3.4配置LDAP、发邮件以及升级到GitLab8.5.4
建议使用非root账户安装,先同步系统时间: ntpdate cn.pool.ntp.org 1.创建用户gitlab 注意:centos下,adduser和useradd的命令效果是一样的,但ubu ...
- Linux使用shell脚本监控
(1)性能监控脚本 performance.sh #!/bin/bash #-------------------------------------------------------------- ...
- Python----MongoDB数据库
什么是MongoDB ? MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统. 在高负载的情况下,添加更多的节点,可以保证服务器性能. MongoDB 旨在为WEB应用提供 ...
- 让5G技术“智慧”生活
1.通讯技术的发展历程 2.5G技术的指标和具体概述 3. 5G的三个关键技术及概述 4.5G的应用场景及业务及安全挑战 如果你认为5G带来的只是下载视频 ...
- W: GPG 错误:http://mirrors.aliyun.com xenial/mongodb-org/3.2 Release: 由于没有公钥,无法验证下列签名: NO_PUBKEY D68FA50FEA312927
更新错误: 正在读取软件包列表... 完成 W: GPG 错误:http://mirrors.aliyun.com xenial/mongodb-org/3.2 Release: 由于没有公钥,无法验 ...
- [刘阳Java]_处理并发有哪些方法
1.HTML静态化 ,将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素2.禁止重复提交:用户提交之后按钮置灰,禁止重复提交3.用户限流:在某一时间段内只允许用户提交一次请求,比如可以采取 ...
- vite插件-自动生成vue组件文档
特点 支持热更新 快速启动,依赖于 vite,无需另起服务 自动生成组件导航 ui 采用了vant-ui的样式 核心方法覆盖率达到了 92.86% 使用 yarn add vite-plugin-vu ...
- Kubernetes部署-RKE自动化部署
一.简介 RKE:Rancher Kubernetes Engine 一个极其简单,闪电般快速的Kubernetes安装程序,可在任何地方使用. 二.准备工作 I.配置系统 系统:CentOS 7 / ...
- 如何热更新长缓存的 HTTP 资源
前言 HTTP 缓存时间一直让开发者头疼.时间太短,性能不够好:时间太长,更新不及时.当遇到严重问题需紧急修复时,尽管后端文件可快速替换,但前端文件仍从本地缓存加载,导致更新长时间无法生效. 对于这个 ...