摘要:Exchange Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger 用于进行 线程间的数据交换。它供一个同步点,在这个同步点,两个线程可以交换彼此 的数据。这两个线程通过 exchange 方法交换数据。 如果第一个线程先执行 exchange()方法,它会一直等待第
阅读全文
摘要:总结 1-Semaphore 的构造方法 Semaphore(int permits)接受一个整型的数字, 表示可用的许可证数量 2-线程使用 Semaphore 的 acquire()方法获取一个许可证,使用完之后调用 release()方法归还许可证。还可以用 tryAcquire()方法尝试获
阅读全文
摘要:CountDownLatch VS CyclicBarrier CountDownLatch 的计数器只能使用一次,而 CyclicBarrier 的计数器可以反复使用 在控制多个线程同时运行上,CountDownLatch 可以不限线程数量,而 CyclicBarrier 是固定线程数。 Cycl
阅读全文
摘要:Fork-Join原理 任务fork,结果join 工作密取 即当前线程的 Task 已经全被执行完毕,则自动取到其他线程的 Task 池中取 出 Task 继续执行。 ForkJoinPool 中维护着多个线程(一般为 CPU 核数)在不断地执行 Task,每 个线程除了执行自己职务内的 Task
阅读全文
摘要:总结 AtomicLong AtomicLong 是基于 CAS 方式自旋更新的。 唯一会制约AtomicLong高效的原因是高并发,高并发意味着CAS的失败几率更高, 重试次数更多,越多线程重试,CAS失败几率又越高,变成恶性循环,AtomicLong效率降低。 LongAdder LongAdd
阅读全文
摘要:什么是原子操作?如何实现原子操作? 假定有两个操作 A 和 B,如果从执行 A 的线程来看,当另一个线程执行 B 时, 要么将 B 全部执行完,要么完全不执行 B,那么 A 和 B 对彼此来说是原子的。 实现原子操作可以使用锁,锁机制,满足基本的需求是没有问题的了,但是 有的时候我们的需求并非这么简
阅读全文
摘要:Lock 接口 Lock 标准用法 在 finally 块中释放锁,目的是保证在获取到锁之后,最终能够被释放。 不要将获取锁的过程写在 try 块中,因为如果在获取锁(自定义锁的实现) 时发生了异常,异常抛出的同时,也会导致锁无故释放。 Lock 常用 API public interface Lo
阅读全文
摘要:总结 先抛出我的结论:用CAS方式获取锁的,并非都是乐观锁。 我们在Java里使用的各种锁,几乎全都是悲观锁。synchronized从偏向锁、轻量级锁到重量级锁,全是悲观锁。JDK提供的Lock实现类全是悲观锁。其实只要有“锁对象”出现,那么就一定是悲观锁。因为乐观锁不是锁,而是一个在循环里尝试C
阅读全文
摘要:总结 1-悲观锁:Java里使用的各种锁:互斥锁、自旋锁、读写锁,都是属于悲观锁。悲观锁做事比较悲观,它认为多线程同时修改共享资源的概率比较高,于是很容易出现冲突,所以访问共享资源前,先要上锁。 2-乐观锁:Java里很少有乐观锁。目前据我所知,java.util.concurrent.atomic
阅读全文
摘要:总结 每个对象有一个监视器锁(monitor)。下面两个方式,本质上都是通过监视器锁(monitor)来控制 同步代码块是通过 monitorenter 和 monitorexit 指令获取线程的执行权 同步方法通过加 ACC_SYNCHRONIZED 标识实现线程的执行权的控制 "同步代码块"的原
阅读全文
摘要:一、什么是死锁 线程死锁是指由于两个或者多个线程互相持有所需要的资源,导致这些线程一直处于等待其他线程释放资源的状态,无法前往执行,如果线程都不主动释放所占有的资源,将产生死锁。当线程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。 二、死锁的四个必要条件 互斥条件:线程要求对所分配的资源
阅读全文
摘要:总结 无锁 -> 偏向锁 -> 轻量级锁 (自旋锁) -> 重量级锁 (悲观锁) 锁状态对比: 偏向锁 轻量级锁 重量级锁 适用场景 只有一个线程进入同步块 虽然很多线程,但是没有冲突:多条线程进入同步块,但是线程进入时间错开因而并未争抢锁 发生了锁争抢的情况:多条线程进入同步块并争用锁 本质 取消
阅读全文
摘要:总结 线程的安全性问题体现在: 原子性:一个或者多个操作在 CPU 执行的过程中不被中断的特性 可见性:一个线程对共享变量的修改,另外一个线程能够立刻看到 有序性:程序执行的顺序按照代码的先后顺序执行 导致原因: 缓存导致的 --> 可见性问题 线程切换带来的 --> 原子性问题 编译优化带来的 -
阅读全文
摘要:总结 Java 为了让大家理解JMM(java memory model, java内存模型)中“内存可见性”的这个概念,提出了 happens-before 的概念。 如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在 happens-before 关系 两个操作之间具有
阅读全文
摘要:总结 根据“任务的性质”分析 CPU 密集型任务 和内存打交道,大量计算。例如大数的计算,正则匹配 如何配置: CPU 密集型任务应配置尽可能小的线程,如配置 Ncpu+1 个线程的线程池(Ncpu 是处理器的核的数目),这样留一个空出来,用来做切换。。 如果线程太多,会造成线程在CPU内部的上下文
阅读全文
摘要:总结 拓扑排序主要用来解决有向图中的依赖解析(dependency resolution)问题。 本质:从入度为0的地点,开启BFS 举例来说,如果我们将一系列需要运行的任务构成一个有向图,图中的有向边则代表某一任务必须在另一个任务之前完成这一限制。那么运用拓扑排序,我们就能得到满足执行顺序限制条件
阅读全文
摘要:总结 Collections.synchronizedXXX() 方法,可以包装成线程安全的容器。 这些方法的作用就是在原有容器的类的方法内部实现逻辑中加入了同步关键字syschronized.
阅读全文
摘要:总结 可以使用 Collections.unmodifiableCollection(Collection c) 方法来创建一个只读集合,这样改变集合的任何操作都会抛出 Java. lang. UnsupportedOperationException 异常。 简单来说就是返回一份map的只读视图,
阅读全文
摘要:总结 底层实现:都是数组,因此get(int index)都是O(1) 线程安全:Vector 的方法都是同步的,线程安全,方法上都有synchronized;ArrayList 非线程安全,但性能比Vector好 扩容机制:默认初始化容量都是10。Vector 扩容默认是原来的2倍,可指定扩容的大
阅读全文
摘要:总结 底层实现: ArrayList 基于动态数组实现的非线程安全的集合。默认大小为10; 当元素个数增加,数据无法存储时,系统会另外申请一个长度为当前长度的1.5倍的数组,然后把之前的数据拷贝到新建的数组中 Arrays.copyOf(objArr, objArr.length + 1) 在声明时
阅读全文
摘要:总结 HashSet实现了Set接口,是一个不能够存放重复元素的容器 内部直接使用HashMap实现,即底层使用数组存储数据(HashMap JDK1.8使用数组+链表+红黑树, HashSet只需要用到数组部分即可,因为保存的都是不相等元素,不存在hash冲突的情况) 线程不安全。如果想变成线程安
阅读全文
摘要:转载 1-TreeMap源码解析(全中文,全函数注释) 作者:孤芳不自賞 2-TreeMap核心源码实现解析 (红黑树的图解) 作者:kosamino
阅读全文
摘要:原文链接 Java进阶之"XML操作" https://zhuanlan.zhihu.com/p/30829960 详细代码参考(必看) XML解析——Java中XML的四种解析方式 1.XML全称是"(扩展标记语言)" 是一种用来结构化文档和数据的通用且适应性强的格式,它不仅仅可以用于 WEB,而
阅读全文
摘要:总结 JDK1.8 主要区别如下: 线程安全性不同。HashMap线程不安全;Hashtable 中的方法是Synchronize的。 key、value是否允许null。HashMap的key和value都是可以是null,key只允许一个null;Hashtable的key和value都不可为n
阅读全文
摘要:图表展示 最新图片,请点击LINK: https://www.processon.com/apps/58bd73cfe4b0f944a6660f38 参考 java集合详解 https://zhuanlan.zhihu.com/p/137999373 Java集合中List,Set以及Map等集合体
阅读全文
摘要:总结 Iterator 可以遍历 Set 和 List 集合,而 ListIterator 只能遍历 List。 Iterator 只能单向遍历,而 ListIterator 可以双向遍历(向前/后遍历)。 ListIterator 从 Iterator 接口继承,然后添加了一些额外的功能,比如添加
阅读全文