第十七天、集合与并发编程

482 阅读4分钟

1. 系统功能树

  • 用例图:关注有哪些角色,角色能够干什么。对需求分析的再次结构化
  • 功能树:关注有哪些大的模块,功能模块能够实现什么能力。对用例图的重新聚合
  • 部署图:关注部署元素(微服务,数据库),关注部署的关联元素

2. Java集合规约

1. Java集合框架图

集合是数据结构的载体,如下图: image.png

2. 数据结构和时间复杂度

  1. 数据的组织方式:线性结构,树结构,图结构,哈希结构等。
  2. 数据处理方式:值逻辑意义上的数据组织方式及其对应的处理方式。数据的处理方式为增、删、查、改,也就是我们经常所说的crud。以特定的算法实现对数据的增加、删除、修改、查找和遍历。
  3. 时间复杂度。 数据结构的优化与运算规模有关,也与调用频率有关。 时间复杂度从最好到最坏的排序如下:
    常数级O(1) > 对数级O(logN) > 线性级O(N) > 线性对数级O(NlogN) > 平方级O(N2) > 指数级O(2N) > 阶乘级O(N!)
  4. HashMap的基本概念
    • table:存储所有节点数据的数组
    • slot:哈希槽。即table[i]的这个位置
    • bucket:哈希桶。table[i]上所有元素形成的表和树的集合
    • HashMap的主干是一个Entry数组。它是HashMap的基本组成单元,每一个Entry都包含Node内部类
  5. HashMap的初始化
HashMap<Integer,String> map = new HashMap<>(13);

以上的代码初始化什么时候分配空间?分配多少存储空间呢? 在HashMap的源代码中,有一个核心方法,该方法用来处理给HaspMap分配空间,一般分配的空间都是2的指数。看下图: image.png 在使用java8的lamda表达式把一个集合处理成map的时候,会发生java.lang.IllegalStateExecption异常,我们查看xxx.stream().college(Collectors.toMap(xxx::getXxx, xxx::getXxx))中toMap的源码可以发现,所以按照java开发手册的规约,我们要加上参数类型为BinaryOperator,参数名为mergeFunction的方法。 image.png 以上虽然可以解决一个报错,但是也会报NPE的错误,通过查看源码可以知道在HashMap的merger方法里面有一个merge方法,会导致空指针异常

image.png 6. ArrayList的subList结果不可以强转为ArrayList 因为subList返回的结果是一个ArrayList的一个内部类(SubList),但是对于所有SubList的操作都会反映到ArrayList上面。所以如果我们直接强转的话,会报ClassCastException异常。

  • 在sublist场景中,高度注意对父集合元素的增加和删除,均会导致子列表的遍历、增加、删除产生ConcurrentModificationException异常
  • 每次sublist子列表的遍历、增加、删除都会调用checkForComodification()

3.并发处理

  • 并行:同时处理多任务的能力
  • 并发:指在某个时间段内,多任务交替处理的能力

1.线程安全

  • 线程安全问题只在多线程环境下才出现,单线程串行执行不存在此问题
  • 保证高并发场景下的线程安全,可以从以下方面来考虑
    • 数据单线程内可见
    • 只读对象
    • 线程安全类
    • 同步与锁机制

2. 什么是锁?

  • 单线程时代没有锁的概念
  • 多线程出现后,就有了资源竞争,就出现了锁机制
  • Java中实现锁的方式:用并发包中的锁类,利用同步代码块

3.AQS透过现象看本质

本质:解决多线程访问共享资源并发问题的同步管理框架

  • Abstract:包含tryAcquire、tryRelease等5个抽象方法,具体的实现由子类实现
  • Queued队列:利用队列来管理竞争共享资源的多线程,这个队列是Node节点的引用虚拟实现
  • Synchronizer同步器:是一个解决多线程同步问题的工具

image.png

4. Lock、AQS和AOS的关系

image.png image.png

5. AQS同步队列

AQS通过CLH机制来管理Node节点的先来厚道,其中依Nodo对象的next、prev串起来的一个双向的同步队列

image.png

6. 线程与线程池的奥秘

  • 线程可以拥有自己的操作栈,程序计数器,局部变量表等资源,它与同一进程内的其他线程共享该进程的所有资源 线程的状态信息: image.png

image.png

image.png

image.png

image.png

7.线程池的作用

  • 利用线程池管理并复用线程,控制最大并发数

  • 增加对线程的管理、快速排查问题

  • 实现任务线程队列缓存策略和拒绝机制

  • 实现某些与时间相关的功能,如定时执行、周期执行等

  • 隔离线程环境。比如在一台机器上面的两个服务,交易和搜索,就可以通过配置独立的线程池,将两个服务进行隔开,防止相互影响。