并发编程专题-基础-2、Synchronized
1. 特性synchronized 是用了 JMM8 大操作的 lock 和 unlock 操作,对主内存中的变量进行了独占操作。 并发编程 3 大特性是可见性,原子性,有序性。 而 synchronized 能同时保证。而 volatile 只能保证可见性,有序性,不能保证原子性 1.1. 原子性原子性指的是在一次或多次操作中,要么所有的操作都执行并且不会受其他因素干扰而中断,要么所有的操作都不执行。 1.2. 可见性可见性是指一个线程对共享变量进行了修改,另一个线程可以立即读取得到修改后的最新值。 1.3. 有序性有序性是指程序中代码的执行顺序,Java 在编译时和运行时会对代码进行优化,会导致程序最终的执行顺序不一定就是我们编写代码时的顺序。 例如,instance = new Singleton() 实例化对象的语句分为三步: 1、分配对象的内存空间; 2、初始化对象; 3、设置实例对象指向刚分配的内存地址; 上述第二步操作需要依赖第一步,但是第三步操作不需要依赖第二步,所以执行顺序可能为:1->2->3、 1->3->2,当执行顺序 ...
Java基础-集合框架-8、HashMap版本变化
脑图https://www.processon.com/view/link/63687577f346fb2f8d429007
Java基础-集合框架-9、集合面试题
1. ConcurrentHashMap 的 size() 方法是线 程安全的吗?为什么 ConcurrentHashMap 的 size() 方法是非线程安全的。也就是说,当有线程调用 put 方法在添加元素的时候,其他线程在调用 size() 方法获取的元素个数和实际存储元素个数是不一致的。原因是 size() 方法是一个==非同步方法==,put() 方法和 size() 方法并没有实现同步锁put() 方法的实现逻辑是:在 hash 表上添加或者修改某个元素,然后再对总的元素个数进行累加。其中,线程的安全性仅仅局限在 hash 表数组粒度的锁同步,避免同一个节点出现数据竞争带来线程安全问题。 数组元素个数的累加方式用到了两个方案: 当线程竞争不激烈的时候,直接用 cas 的方式对一个 long 类型的变量做原子递增。 当线程竞争比较激烈的时候,使用一个 CounterCell 数组,用分而治之的思想减少多线程竞争,从而实现元素个数的原子累加。 size() 方法的逻辑就是遍历 CounterCell 数组中的每个 value 值进 ...
Java基础-集合框架-7、ConcurrentHashMap(JDK1.8)
1. 容器初始化https://www.bilibili.com/video/BV17i4y1x71z?t=421.7 1.1. 源码分析 在 jdk8 的 ConcurrentHashMap 中一共有 5 个构造方法,这四个构造方法中都没有对内部的数组做初始化, 只是对一些变量的初始值做了处理 jdk8 的 ConcurrentHashMap 的数组初始化是在第一次添加元素时完成 PS: 传入 32,最终大小为 64,与前面的都不同 注意,调用这个方法,得到的初始容量和我们之前讲的 HashMap 以及 jdk7 的 ConcurrentHashMap 不同,即使你传递的是一个 2 的幂次方数,该方法计算出来的初始容量依然是比这个值大一点的 2 的幂次方数 JDK1.8: 传递进来一个初始容量,ConcurrentHashMap 会基于这个值计算一个比这个值大一半的 2 的幂次方数作为初始容量 12345678910111213//没有维护任何变量的操作,如果调用该方法,数组长度默认是16 public ConcurrentHashMap() { } ...
Java基础-集合框架-6、ConcurrentHashMap(JDK1.7)
1. Unsafe 介绍1.1. 1、Unsafe 简介Unsafe 类相当于是一个 java 语言中的后门类,提供了硬件级别的原子操作,所以在一些并发编程中被大量使用。jdk 已经作出说明,该类对程序员而言不是一个安全操作,在后续的 jdk 升级过程中,可能会禁用该类。所以这个类的使用是一把双刃剑,实际项目中谨慎使用,以免造成 jdk 升级不兼容问题。 1.2. 2、Unsafe Api这里并不系统讲解 Unsafe 的所有功能,只介绍和接下来内容相关的操作 arrayBaseOffset:获取数组的基础偏移量 arrayIndexScale:获取数组中元素的偏移间隔,要获取对应所以的元素,将索引号和该值相乘,获得数组中指定角标元素的偏移量 getObjectVolatile:获取对象上的属性值或者数组中的元素 getObject:获取对象上的属性值或者数组中的元素,已过时 putOrderedObject:设置对象的属性值或者数组中某个角标的元素,更高效 putObjectVolatile:设置对象的属性值或者数组中某个角标的元素 putObject:设置对象的属性值或者数组中某个 ...
001-基础知识专题--关键字和接口-1、Serializable接口
1. 系列化的用途 想把的内存中的对象状态保存到一个文件中或者数据库中时候 网络通信时需要用套接字在网络中传送对象时,如我们使用 RPC 协议进行网络通信时 2. 如何序列化只要一个类实现 Serializable 接口,那么这个类就可以序列化了。 3. 关于 serialVersionUID在反序列化的过程中则需要使用 serialVersionUID 来确定由那个类来加载这个对象,所以我们在实现 Serializable 接口的时候,一般还会要去尽量显示地定义 serialVersionUID,如: 1private static final long serialVersionUID = 1L; 在反序列化的过程中,如果接收方为对象加载了一个类,如果该对象的 serialVersionUID 与对应持久化时的类不同,那么反序列化的过程中将会导致 InvalidClassException 异常。例如,在之前反序列化的例子中,我们故意将 User 类的 serialVersionUID 改为 2L,如: 1private static final long serialVer ...
Java基础-集合框架-4、LinkedList
1. 源码解读 2. 与 ArrayList 对比 是否保证线程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全; 底层数据结构: Arraylist 底层使⽤的是 Object 数组; LinkedList 底层使⽤的是 双向链表 数据结构(JDK1.6 之前为循环链表,JDK1.7 取消了循环。注意双向链表和双向循环链表的区别,下⾯有介绍到!) 插⼊和删除是否受元素位置的影响:① ArrayList 采⽤数组存储,所以插⼊和删除元素的时间复杂度受元素位置的影响。 ⽐如:执⾏ add(E e) ⽅法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是 O(1)。但是如果要在指定位置 i 插⼊和删除元素的话( add(int index, E element) )时间复杂度就为 O(n-i)。因为在进⾏上述操作的时候集合中第 i 和第 i 个元素之后的 (n-i) 个元素都要执⾏向后位/向前移⼀位的操作。② LinkedList 采⽤链表存储,所以对于 add(E e) ⽅法的插⼊,删除元素时 ...
Java基础-集合框架-5、HashMap
1. 数据结构(哈希表)hashtable(哈希表) 1.1. 是什么散列表(Hash table,也叫哈希表),是根据关键码值 (Key value) 而直接进行访问的 数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做 散列函数,存放记录的 数组 叫做 散列表给定表 M,存在函数 f(key),对任意给定的关键字值 key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表 M 为哈希 (Hash)表,函数 f(key) 为哈希 (Hash) 函数。 1.2. 特点hash 表 也叫散列表;特点:快 很快 神奇的快 结构:结构有多种。最流行、最容易理解:顺序表 + 链表 主结构:顺序表,每个顺序表的节点在单独引出一个链表 在无序数组中按照内容查找,效率低下,时间复杂度是 O(n) 在有序数组中按照内容查找,可以使用折半查找,时间复杂度 O(log2n) 问题:按照内容查找,能否也不进行比较,而是通过计算得到地址,实现类似数组按照索引查询的高效率 O(1) 呢 有!!!哈希表来实现 1.3. 哈希函数 1.4. native ...
Java基础-集合框架-1、集合关系及概念
1. 集合类继承关系 2. 初始容量 加载因子 初始容量 加载因子 ArrayList 0 1.5X LinkedList Vector 2X HashMap CurrentHashMap 3. List,Set,Map 三者的区别Java 容器分为 Collection 和 Map 两大类,Collection 集合的子接口有 Set、List、Queue 三种子接口。我们比较常用的是 Set、List,Map 接口不是 collection 的子接口。 Collection 集合主要有 List 和 Set 两大接口 1. List:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可以重复,可以插入多个 null 元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector。 2. Set:一个无序(存入和取出顺序有可能不一致)容器,不可以存储重复元素,只允许存入一 个 null 元素,必须保证元素唯一性。Set 接口常用实现类 ...
Java基础-集合框架-3、ArrayList
1. 特点 2. 内存结构图 3. 底层原理4. 扩容方法 这里需要注意一点,因为扩容操作涉及内存申请和数据搬移,是比较耗时的。所以,如果事先能确定需要存储的数据大小,最好 在创建 ArrayList 的时候事先指定数据大小。 比如我们要从数据库中取出 10000 条数据放入 ArrayList。我们看下面这几行代码,你会发现,相比之下,事先指定数据大小可以省掉很多次内存申请和数据搬移操作。 4.1. jdk 区别jdk8:ArrayList 中维护了 Object[] elementData,初始容量为 0. 第一次添加时,将初始 elementData 的容量为 10 再次添加时,如果容量足够,则不用扩容直接将新元素赋值到第一个空位上 如果容量不够,会扩容 1.5 倍 jdk7:ArrayList 中维护了 Object[] elementData,初始容量为 10. 添加时,如果容量足够,则不用扩容直接将新元素赋值到第一个空位上 如果容量不够,会扩容 1.5 倍 jdk7 和 jdk8: 区别:jdk7 相当于饿汉式,创建对象时,则初始容量为 10 jdk8 相当于懒汉式,创建对 ...
