JUC 中倒数计数器 CountDownLatch 的使用与原理分析,当需要等待多个线程执行完毕后在做一件事情时候 CountDownLatch 是比调用线程的 join 方法更好的选择,CountDownLatch 与 线程的 join 方法区别是什么? 日常开发中经常会遇到需要在主线程中开启多线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后再进行汇总的场景,它的内部提供了一个计数器,在构造闭锁时必须指定计数器的初始值,且计数器的初始值必须大于0.另外它还提供了一个countDown…
我们知道在解决线程安全问题上使用 ReentrantLock 就可以,但是 ReentrantLock 是独占锁,同时只有一个线程可以获取该锁,而实际情况下会有写少读多的场景,显然 ReentrantLock 满足不了需求,所以 ReentrantReadWriteLock 应运而生,ReentrantReadWriteLock 采用读写分离,多个线程可以同时获取读锁. 首先我们先看一下,ReentrantReadWriteLock 内部构造先看下它的类图结构如下图所示: 如上图可以看到读写锁内…
一.LongAdder原理 LongAdder类是JDK1.8新增的一个原子性操作类.AtomicLong通过CAS算法提供了非阻塞的原子性操作,相比受用阻塞算法的同步器来说性能已经很好了,但是JDK开发组并不满足于此,因为非常搞并发的请求下AtomicLong的性能是不能让人接受的. 如下AtomicLong 的incrementAndGet的代码,虽然AtomicLong使用CAS算法,但是CAS失败后还是通过无限循环的自旋锁不多的尝试,这就是高并发下CAS性能低下的原因所在.源码如下: p…
一.背景 要实现对队列的安全访问,有两种方式:阻塞算法和非阻塞算法.阻塞算法的实现是使用一把锁(出队和入队同一把锁ArrayBlockingQueue)和两把锁(出队和入队各一把锁LinkedBlockingQueue)来实现:非阻塞算法使用自旋+CAS实现. 今天来探究下使用非阻塞算法来实现的线程安全队列ConcurrentLinkedQueue,它是一个基于链接节点的无界线程安全队列,采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会…
一.前言 前文探究了非阻塞算法的实现ConcurrentLinkedQueue安全队列,也说明了阻塞算法实现的两种方式,使用一把锁(出队和入队同一把锁ArrayBlockingQueue)和两把锁(出队和入队各一把锁LinkedBlockingQueue)来实现,今天来探究下ArrayBlockingQueue. ArrayBlockingQueue是一个阻塞队列,底层使用数组结构实现,按照先进先出(FIFO)的原则对元素进行排序. ArrayBlockingQueue是一个线程安全的集合,通过…
java并发编程笔记(六)--AQS 使用了Node实现FIFO(first in first out)队列,可以用于构建锁或者其他同步装置的基础框架 利用了一个int类型表示状态 使用方法是继承 子类通过继承并通过实现它的方法管理其状态(acquire和release)的方法操纵状态 可以同时实现排它锁和共享锁模式(独占.共享) AQS同步组件 CountDownLatch Semaphore CyclicBarrier ReentrantLock Condition FutureTask C…
java并发编程笔记(三)--线程安全性 线程安全性: ​ 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的. 线程安全体现在三个方面: 原子性:提供了互斥访问,同一时刻只能有一个线程来对它进行操作 可见性:一个线程对主内存的修改可以及时的被其他线程观察到 有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序的存在,该观察结果一般杂乱无序. 原子性:Atom…
java并发编程笔记(二)--并发工具 工具: Postman:http请求模拟工具 Apache Bench(AB):Apache附带的工具,测试网站性能 JMeter:Apache组织开发的压力测试工具 代码:Semaphone.CountDownLatch等 PostMan: Apache Bench(AB) ab -n [请求总数] -c [本次请求的并发数是50] [url] 例如:ab -1000 -c 50 http://www.baidu.com JMeter 一个图形化的工具,…
java并发编程笔记(一)--简介 线程不安全的类示例 public class CountExample1 { // 请求总数 public static int clientTotal = 5000; // 同时并发执行的线程数 public static int threadTotal = 200; public static int count = 0; public static void main(String[] args) throws Exception { ExecutorS…
Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo CountDownLatch countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行. 是通过一个计数器来实现的,计数器的初始值是线程的数量.每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了. CountDownLatch中的方法 //调用await()方法的线程会被挂起,它会等待直到c…
java并发编程笔记(十一)--高并发处理思路和手段 扩容 垂直扩容(纵向扩展):提高系统部件能力 水平扩容(横向扩容):增加更多系统成员来实现 缓存 缓存特征 命中率:命中数/(命中数+没有命中数) 一.影响因素 业务场景和业务需求 缓存的设计(粒度和策略) 缓存的容量和基础设施 二.缓存分类和应用场景 本地缓存:编程实现(成员变量,局部变量,静态变量).Guava Cache 分布式缓存:Memcache.Redis 三.常用组件 Guava Cache public class Guava…
java并发编程笔记(十)--HashMap与ConcurrentHashMap HashMap参数 有两个参数影响他的性能 初始容量(默认为16) 加载因子(默认是0.75) HashMap寻址方式 对一个我们需要插入的数据或者我们要读取的数据,首先hashMap会将它的key按照一定的计算规则计算出的hash值并对我们的数组长度进行取模,结果作为插入数组织位置的index. 在计算中,取模的代价远远高于位移的代价,因此hashMap要求数组的长度一定是2的n次方:此时它将key的hash值对…
java并发编程笔记(九)--多线程并发最佳实践 使用本地变量 使用不可变类 最小化锁的作用域范围 使用线程池Executor,而不是直接new Thread执行 宁可使用同步也不要使用线程的wait和notify 使用BlockingQueue实现生产-消费模式 使用并发集合而不是加了锁的同步集合(比如Collections.synchronized这些集合尽量避免使用,应该用J.U.C中提供的专门的同步集合) 使用Semaphore创建有界的访问 宁可使用同步代码块,也不要使用同步的方法 避…
java并发编程笔记(八)--死锁 死锁发生的必要条件 互斥条件 进程对分配到的资源进行排他性的使用,即在一段时间内只能由一个进程使用,如果有其他进程在请求,只能等待. 请求和保持条件 进程已经保持了至少一个资源,但是又提出了新的资源请求,而该资源又被其他进程占有,造成请求阻塞,但是又对自己已经占有的资源不放 不剥夺条件 是指进程在对已经占有的资源未使用完的情况下,不能被剥夺,只能在使用完时自己释放 环路等待条件 public class DeadLock implements Runnable…
java并发编程笔记(七)--线程池 new Thread弊端 每次new Thread新建对象,性能差 线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能占用过多系统资源导致死机或者OOM 缺少更多功能,如更多执行.定期执行.线程中断 线程池的好处 重用存在的线程,减少对象创建.消亡的开销,性能佳 可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞 提供定时执行.定期执行.单线程.并发数控制等功能 ThreadPoolExecutor 重要核心参数 core…
java并发编程笔记(五)--线程安全策略 不可变得对象 不可变对象需要满足的条件 对象创建以后其状态就不能修改 对象所有的域都是final类型 对象是正确创建的(在对象创建期间,this引用没有逸出) final关键字:类.方法.变量 修饰类:不能被继承 修饰方法:1.锁定方法不被继承类修改:2.效率,目前近期版本已经将私有方法默认设置为final,final能够使方法转为内嵌调用. 修饰变量:基本数据类型变量.引用类型变量 定义不可变对象的其他方法: Collections.unmodifi…
java并发编程笔记(四)--安全发布对象 发布对象 使一个对象能够被当前范围之外的代码所使用 对象逸出 一种错误的发布.当一个对象还没构造完成时,就使它被其他线程所见 不安全的发布对象 某一个类的构造方法为公共的. 如: public class UnsafePublish { private String[] states = {"a", "b", "c"}; public String[] getStates() { return stat…
我们以ByteArrayInputStream,拉开对字节类型的“输入流”的学习序幕.本章,我们会先对ByteArrayInputStream进行介绍,然后深入了解一下它的源码,最后通过示例来掌握它的用法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_02.html ByteArrayInputStream 介绍 ByteArrayInputStream 是字节数组输入流.它继承于InputStream.它包含一个内部缓冲区,该缓冲区包含从流…
前面学习ByteArrayInputStream,了解了“输入流”.接下来,我们学习与ByteArrayInputStream相对应的输出流,即ByteArrayOutputStream.本章,我们会先对ByteArrayOutputStream进行介绍,在了解了它的源码之后,再通过示例来掌握如何使用它. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_03.html ByteArrayOutputStream 介绍 ByteArrayOutpu…
目录 Java 序列化和反序列化(三)Serializable 源码分析 - 2 1. ObjectStreamField 1.1 数据结构 1.2 构造函数 2. ObjectStreamClass 2.1 数据结构 2.2 构造函数 2.3 提取序列号:getDeclaredSUID 2.4 提取需要序列化字段:getSerialFields 2.5 其它方法 Java 序列化和反序列化(三)Serializable 源码分析 - 2 在上一篇文章中围绕 ObjectOutputStream…
目录 Java 序列化和反序列化(二)Serializable 源码分析 - 1 1. Java 序列化接口 2. ObjectOutputStream 源码分析 2.1 ObjectOutputStream 数据结构 2.2 ObjectOutputStream 构造函数 2.3 序列化入口:writeObject 2.4 核心方法:writeObject0 2.5 序列化:writeOrdinaryObject 2.6 类信息序列化:writeClassDesc 2.7 类数据信息序列化:w…
在多线程环境下,使用HashMap进行put操作时存在丢失数据的情况,为了避免这种bug的隐患,强烈建议使用ConcurrentHashMap代替HashMap. HashTable是一个线程安全的类,它使用synchronized来锁住整张Hash表来实现线程安全,即每次锁住整张表让线程独占,相当于所有线程进行读写时都去竞争一把锁,导致效率非常低下.ConcurrentHashMap可以做到读取数据不加锁,并且其内部的结构可以让其在进行写操作的时候能够将锁的粒度保持地尽量地小,允许多个修改操作…
一.Unsafe类的源码分析 JDK的rt.jar包中的Unsafe类提供了硬件级别的原子操作,Unsafe里面的方法都是native方法,通过使用JNI的方式来访问本地C++实现库. rt.jar 中 Unsafe 类主要函数讲解, Unsafe 类提供了硬件级别的原子操作,可以安全的直接操作内存变量,其在 JUC 源码中被广泛的使用,了解其原理为研究 JUC 源码奠定了基础. 首先我们先了解Unsafe类中主要方法的使用,如下: 1.long objectFieldOffset(Field…
本文将主要讲述 AbstractQueuedSynchronizer 的内部结构和实现逻辑,在看本文之前最好先了解一下 CLH 队列锁,AbstractQueuedSynchronizer 就是根据 CLH 队列锁的变种实现的,因为本身 AQS 比较复杂不容易看清楚他本身的实现逻辑,所以查看 CLH 队列锁的实现,可以帮助我们理清楚他内部的关系:关于队列锁的内容可以参考 ,CLH.MCS 队列锁简介 : 一.AQS 结构概述 在 JDK 中除 synchronized 内置锁外,其他的锁和同步组…
今天要介绍的是List接口中最常用的实现类——ArrayList,本篇的源码分析基于JDK8,如果有不一致的地方,可先切换到JDK8后再进行操作. 本篇的内容主要包括这几块: 1.源码结构介绍 2.源代码展示 3.要点说明 4.优缺点说明 一.源码结构介绍 ArrayList的源码跟之前的接口源码比起来,那可就不能同日而语了,一千多行代码,如果直接看的话确实有些费劲,但仔细看看就会发现,其实大致结构是这样的: 其中包含了好四个内部类:     ArrayListSpliterator:Array…
转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的spring工程,甚至是servlet工程,都是一样的,只不过配置一些监听器的方法不同而已. 本文经过作者实践,确认完美运行. 二:Spring boot使用websocket 2.1:依赖包 websocket本身是servlet容器所提供的服务,所以需要在web容器中运行,像我们所使用的tomcat,当然…
目录 CAS原理 AtomicInteger Unsafe AtomicReference AtomicStampedReference AtomicIntegerArray AtomicIntegerFieldUpdater 无锁的Vector 无锁即无障碍的运行, 所有线程都可以到达临界区, 接近于无等待. 无锁采用CAS(compare and swap)算法来处理线程冲突, 其原理如下 CAS原理 CAS包含3个参数CAS(V,E,N).V表示要更新的变量, E表示预期值, N表示新值.…
前面花了好几篇的篇幅把HashMap里里外外说了个遍,大家可能对于源码分析篇已经讳莫如深了.别慌别慌,这一篇来说说集合框架里最偷懒的一个家伙——HashSet,为什么说它是最偷懒的呢,先留个悬念,看完本文之后,你就会知道所言不假了. 本篇将从以下几点来进行介绍: 1.HashSet的特点和使用场景 2.HashSet的示例 3.HashSet的继承结构图 4.HashSet的源码解析 HashSet的特点和使用场景 HashSet是Set家族的一员,所以也具有着Set的全部性质,比如元素无序,元…
该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Selector的创建在Windows下默认生成WindowsSelectorImpl对象,那么Selector的select方法使用的就是WindowsSelectorImpl的select方法,而在WindowsSelectorImpl下并没有覆盖这个方法,而是由其基类SelectorImpl实现的: pu…
一.同步容器: 1.Vector容器实现了List接口,Vector实际上就是一个数组,和ArrayList类似,但是Vector中的方法都是synchronized方法,即进行了同步措施.保证了线程安全.源码如下图: 可以看到这些方法都加了synchronized.即加了同步操作. 2.Hashtable集合.HashTable实现了Map接口,它和HashMap很相似,但是HashTable进行了同步处理,而HashMap没有源码如下: 可以看到HashTable的实现方法也用到了synch…