首页 > 技术文章 > to meet you 常用类库与技巧

zyy1688 2019-07-09 13:59 原文

1、Java的异常体系

2、从概念角度解析Java的异常处理机制

3、从责任角度看Java的异常体系

 

checked exception 必须try catch 或者继续向上抛出异常,否则编译不能通过

4:常见Error以及Exception

5:Java的异常处理机制

 

6:Java异常的处理原则

7:try-catch的性能

 

8:Collection体系

 

9:集合之List和Set

 

 

10:HashMap、HashTable、ConccurentHashMap

  10.1HashMap(Java8以前):数组+链表

          hash(key.hashCode())%len

  

 

  HashMap(Java8及以后):数组+链表+红黑树

    性能从O(n)提高到O(logn)

  

 10.2

 10.3

10.4:

10.5:

 

 10.6:

如何优化Hashtable?

  • 通过锁细粒度化,将整锁拆解多个锁进行优化

  早期的ConcurrentHashMap:通过分段锁Segment来实现

  数据+链表

  

ConcurrentHashMap

  当前的ConcurrentHashMap:CAS+synchronized使锁更细化

  数组+链表+红黑树

  

ConcurrentHashMap:put方法的逻辑

  1. 判断Node[]数组是否初始化,没有则进行初始化操作
  2. 通过hash定位数组的索引坐标,是否有Node节点,如果没有则使用CAS进行添加(链表的头结点),添加失败则进入下次循环
  3. 检查到内部正在扩容,就帮助它一块扩容
  4. 如果f!=null,则使用synchronized锁住f元素(链表/红黑二叉树的头元素)
    1. 如果是Node(链表结构)则执行链表ode添加操作
    2. 如果是TreeNode(树形结构)则执行树添加操作
  5.  判断链表长度已经达到临界值,当然这个8是默认值,大家也可以去做调整,当节点数超过这个值就需要把链表转换为树结构

ConcurrentHashMap总结:比起Segment,锁拆的更细

  • 首先使用无锁操作CAS插入头结点,失败则循环重试
  • 若头结点已存在,则尝试获取头结点的同步锁,再进行操作

 ConcurrentHashMap:注意

  • size()和mappingCount()的一桶,两者计算是否准确
  • 多线程环境下如何进行扩容

 

10.7:

三者的区别

  • HashMap线程不安全,数组+链表+红黑树
  • Hashtable线程安全,锁住整个对象,数组+链表
  • ConcurrentHashMap线程安全,CAS+同步锁,数组+链表+红黑树
  • HashMap的key、value均可为null,而其他的两个类不支持

 

10.8:

arrayList 是通过Array.copy进行扩容的
hashmap 非线程安全的 延迟加载在首次使用才初始化
static final int TREEIFY_THRESHOLD = 8;
static final int UNTREEIFY_THRESHOLD = 6;
两个参数设置红黑树和链表相互转换的阈值
默认负载因子是0.75
扩容:将会创建原来两倍大小的扩容并重新hash
ConcurrentHashMap线程安全,CAS+同步锁,数组+链表+红黑树 锁的是链表/红黑二叉树的头元素

 

 

三. J.U.C知识点梳理

 

 

 

NIO初窥

Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API

核心组件:Channel、Buffers和Selector

NIO和IO主要区别

特征NIOIO
  基于通道(Channel)和缓冲区 基于字节流和字符流
阻塞 非阻塞IO 阻塞IO
选择器 有选择器(监听多个通道的事件) 无选择器
    • Channel与Buffer:基本上所有的IO在NIO都从一个Channel开始。Channel有点像流,数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。

    • JAVA NIO中,Channel的主要实现方法有:FileChannel、DatagramChannel、SocketChannel、ServerSocketChannel

    • JAVA NIO中,Buffer的主要实现方法有:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer等

    • Selector :Selector允许单线程处理多个 Channel。例如在一个聊天服务器中,一个应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。如图: 

推荐阅读