
Java高并发
文章平均质量分 94
ONROAD0612
不问前程何如,但愿落幕无悔
展开
-
jUC--PriorityBlockingQueue源码分析(基于JDK1.8)
1 概述在阅读这一篇文章之前,建议大家线阅读我的另一篇文章JUC--PriorityQueue源码分析(基于JDK1.8)。PriorityBlockingQueue是有界的阻塞队列,根据这个名字我们就可以看出PriorityBlockingQueue的数据存储原理和PriorityQueue是相同的,都采用了最小堆的逻辑,并且使用了数据来存储数据。所不同的就是这个优先队列时候线程安全的,...原创 2019-02-27 11:14:36 · 308 阅读 · 0 评论 -
JUC--Semaphore源码分析(基于JDK1.8)
1 概述通过前面(参考JUC-- Semaphore学习(一)简介和使用 )对Semaphore的介绍,我们对Semaphore有了一个基本的认识,我们知道Semaphore通常用于限制对资源使用的线程数量,现在就要针对Semaphore的源码进行分析,Semaphore的结构如下:从上图我们可以发现,这里又出现了AQS的身影,我们可以看出AQS的重要性。所以再学习JUC的时候非常有必...原创 2018-09-07 17:23:22 · 331 阅读 · 1 评论 -
JUC--ConcurrentHashMap源码分析(一)(基于JDK1.7)
1 概述前面分析研究了HashMap,我们知道HashMap不是线程安全的,那么如果需要线程安全的HashMap怎么办呢?这个时候我们有几种解决方法。(1)使用HashTable代替HashMap;(2)使用Collections.synchronizeMap(hashMap);(3)使用ConcurrentHashMap;针对这三种方法得区别我们在文章后面再谈,下面我们就针对...原创 2018-09-18 11:02:34 · 286 阅读 · 0 评论 -
JUC--Semaphore简介和使用
1 概述通过查看JDK的API,我们可以发现对Semaphore的定义如下:信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。Semaphore(信号量)限制着访问某些资源...原创 2018-09-06 16:22:50 · 469 阅读 · 0 评论 -
JUC--CyclicBarrier源码分析(基于JDK1.8)
1 概述通过前面对CyclicBarrier(请参考JUC-- CyclicBarrier学习(一)简介和使用)的介绍,我们对CyclicBarrier的使用有了一个深度的认识,现在就要针对CyclicBarrier的源码进行分析,CyclicBarrier的结构如下:从上图我们可以猜想CyclicBarrier的实现主要就是依靠ReentrantLock和Condition。2 ...原创 2018-09-06 10:38:11 · 289 阅读 · 0 评论 -
JUC--CyclicBarrier简介和使用
1 概述CyclicBarrier允许一组线程相互等待,直到到达某个公共的屏障点这组线程才继续执行。在涉及一组固定大小的线程的程序当中,这组线程必须相互等待,这个时候CyclicBarrier就显得非常有用了,由于Barrier(栅栏)在释放线程后可以从新使用,所以Barrier被称为Cyclic(循环)Barrier(栅栏)。2 示例下面我们来看看CyclicBarrier是如何使用...原创 2018-09-06 09:22:03 · 371 阅读 · 0 评论 -
JUC--Condition源码分析(基于JDK1.8)
1 概述通过前面的文章(JUC--Condition学习(一)简介和使用),我们对Condition有了一个初步的认识,并且我们也知道了如何使用Condition,现在我们就来看一看Condition到底是如何实现线程的等待和唤醒的。2 等待队列在我们学习AQS的时候,我们知道当线程获取锁失败的时候会进入CLH队列,以等待状态(WAITING)存在于同步队列。而当我们调用Conditi...原创 2018-09-04 11:46:11 · 562 阅读 · 0 评论 -
JUC--Condition简介和使用
1 概述我们知道针对synchronized关键字实现的加锁操作操作我们可以使用wait和notify来实现线程的等待和唤醒线程,但是我们清楚这个时候就只能有一个线程进入等待,那么如果我们想要多个线程等待,同时我们可以唤醒多个线程怎么办呢?这个时候就需要用到Lock对应的Condition来完成了。我们知道针对Lock与synchronized的区别在于,Lock的操作更加灵活,并且可以响...原创 2018-09-04 10:24:09 · 2111 阅读 · 0 评论 -
JUC--ReenTrantLock学习(一)简介与使用
1 概述对java多线程编程有一定掌握的同学肯定知道synchronized关键字来实现对共享对象的加锁。synchronized关键字加锁无法对所进行手动加锁和释放,并且容易造成死锁。那么有没有一种工具类能够实现手动加锁和释放呢?并且针对获取锁的操作我们可以在一定时间如果无响应就返回呢?当然有,这就是我们接下来要提到的ReenTrantLock。2 ReentrantLock实现简介...原创 2018-08-21 11:50:12 · 560 阅读 · 0 评论 -
JUC--ReenTrantLock学习(二)源码分析之获取锁
1 概述前面我们学习了ReentrantLock的用法以及与synchronized的比较(详情请参考这篇文章:JUC--ReenTrantLock学习(一)简介与使用),同时也对AQS有了初步掌握,我们知道AQS是JUC里面大部分工具实现的基础类,并且使用了模板方法模式了实现JUC工具类。现在我们就开始对ReenTrantLock的源码进行学习。首先我们还是来看一下ReentrantLo...原创 2018-08-23 14:16:27 · 380 阅读 · 0 评论 -
JUC--ConcurrentHashMap源码分析(二)(基于JDK1.8)
1 概述前面我们分析了ConcurrentHashMap(JDK1.7)(请参考JUC--ConcurrentHashMap源码分析(一)(基于JDK1.7))和HashMap(JDK1.8)(请参考Java集合框架--HashMap源码分析(二)(基于JDK1.8))的源码,我们直到ConcurrentHashMap其实就是针对HashMap(JDK1.7)进行了分段加锁的方式,也就是针对H...原创 2018-09-25 11:19:48 · 459 阅读 · 0 评论 -
JUC--队列概述
1 概述Java中的队列是一个FIFO的数据结构,适用于生产者消费者模式。Queue接口与List、Set同一级别,都是继承了Collection接口,LinkedList也实现了Deque接口。当然java中的队列有阻塞和非阻塞队列,下面我们就来看一看Java中队列都有哪些实现。2 类图下面我们来看一下java中队列的家庭成员。3 详细说明3.1 QueueQue...原创 2018-09-26 19:52:53 · 854 阅读 · 0 评论 -
jUC--DelayQueue源码分析(基于JDK1.8)
1 概述DelayQueue是一个有界的阻塞队列,这里面的元素具有延迟释放的功能,仅仅当元素的延迟时间到了的时候才能够被获取。队列的头节点是延迟时间最久的元素。如果没有元素的延迟时间过期,这里将没有头节点,而且poll函数将返回null。这个工具主要用来标记那些应该在给定时间之后实现的对象。注意:这个工具是线程安全的。2 基本信息DelayQueue是一个阻塞的延迟队列,针对添加到...原创 2019-02-26 19:57:10 · 413 阅读 · 0 评论 -
JUC--PriorityQueue源码分析(基于JDK1.8)
1 概述PriorityQueue是基于优先堆实现的无界优先队列,它的底层是通过最小堆来实现的。我们知道普通的队列具有FIFO的特性,队列的出和入与进入队列的时间有关,但是针对优先队列,每个队列的元素中都有一个属性来表示队列的优先级,然后队列的出队就根据队列中元素的优先级来确定先后顺序。这样就可以实现生活中一些需要根据优先级来处理数据的场景,比如说根据会员级别,优先消费的场景。下面我们来看看P...原创 2019-02-25 17:53:20 · 292 阅读 · 0 评论 -
JUC--ConcurrentSkipListSet源码分析(基于JDK1.8)
1 概述前面的文章中,我们分析了HashSet的实现原理(可以参考Java集合框架--HashSet源码分析(基于JDK1.8))。HashSet的实现其实是依赖于HashMap的,直接使用了HashMap的key来存储HashSet的值,对应的HashMap的value就存为虚拟值。所以,在这里我们可以大胆猜测ConcurrentSkipListSet的实现是完全依赖于ConcurrentS...原创 2019-02-25 16:29:45 · 363 阅读 · 0 评论 -
JUC--ConcurrentSkipListMap源码分析(基于JDK1.8)
1 概述我们知道JDK针对键值对的存储提供了HashMap、TreeMap、HashTable和ConcurrentHashMap等工具。这些工具在多线程的情况下,使存入的数据有序同时方便数据的遍历,就显得不那么理想了,所以JDK又为我们提供了一个工具ConcurrentSkipListMap。这个工具能够保证线程安全,同时保证插入数据使有序的(根据key来排序)。下面我们就开始来分析一下Co...原创 2019-02-25 11:20:48 · 431 阅读 · 0 评论 -
jUC--LinkedTransferQueue源码分析(基于JDK1.8)
1 概述LinkedTransferQueue是一个基于链表的阻塞队列。采用了一种预占模式。消费者线程获取数据的时候,如果在队列中没有任何数据,则消费者线程生成一个节点,这个节点的元素为空,然后消费者线程等待在这个节点上。当生产者线程入队的时候发现了有意个元素为空的节点,则直接将数据赋予这个节点,并且唤醒节点上的等待线程。如果没有元素为空的节点,则根据how进行入队。下面我们来看一下具体使用方...原创 2019-02-28 09:41:22 · 357 阅读 · 0 评论 -
JUC--CopyOnWriteArraySet源码分析(基于JDK1.8)
1 概述有一定Java基础知识的同学都知道HashSet是通过散列表实现的,并且存储的内容是无序的而且不能重复。但是HashSet有一个比较明显的缺点,就是HashSet不是线程安全的,那么有没有线程安全的HashSet呢?在这里我们就可以引出CopyOnWriteArraySet了。CopyOnWriteArraySet提供根据读写分离的思想,提供了线程安全的HashSet的功能,但是C...原创 2019-02-22 14:36:20 · 360 阅读 · 0 评论 -
JUC--CopyOnWriteArrayList源码分析(基于JDK1.8)
1 概述我们来设想一个场景,在并发的情况下,我们想要使用一个List来保存对象,这个时候为了让List是线程安全的,我们能怎么做呢?首先我们能够想到的应该是使用synchronized对List对象加锁,或者在使用List对象的地方使用ReentrantLock来保证线程同步,但是这样就有一个问题,我们知道对List中的对象进行读操作的时候并不会存在数据一致性的问题,只有在写的时候才有数据一致...原创 2019-02-22 13:50:56 · 313 阅读 · 0 评论 -
Java的Future模式(基于JDK1.8)
1 概述在我们使用多线程的时候,如果我们需要在主线程中拿到其余线程执行输出的内容,同时在子线程运行的时候,我们主线程依然运行,只是在合适的时候来拿子线程的结果就行了,这个时候我们怎么办呢?这就需要用到Future模式了。下面我们直接上一个列子来直观地演示Future模式。2 实例import java.util.concurrent.Callable;import java.uti...原创 2019-02-22 10:44:05 · 489 阅读 · 0 评论 -
JUC--LinkedBlockingQueue源码分析 (基于JDK1.8) 未完待续
1 概述LinkedBlockingQueue是一个有界性可选的阻塞队列,也就是再初始化的时候如果设置了大小,则大小就是固定的,否则队列的大小为Integer.MAX_VALUE。通常为了防止数据的膨胀,我们通常再初始化的时候给链表设置一个初始大小。LinkedBlockingQueue是基于链表实现的一个FIFO队列,链表的首节点是添加时间最久的数据,而链表的尾节点是最早添加的数据,所以...原创 2018-09-27 20:36:17 · 247 阅读 · 0 评论 -
JUC--ArrayBlockingQueue源码分析 (基于JDK1.8)
1 概述这是一个依赖于数组实现的有界的阻塞队列,采用先进先出的规则,队列的头元素是入队最久的元素,队列的尾元素是入队时间最晚的元素。队列的大小在队列初始化的时候一旦确定了就没法进行改变,当尝试向满队列中插入数据和从空队列中获取数据都将产生阻塞。另一方面这个队列也可以保证等待线程的公平性,只需要再初始化的时候设置公平性即可,当然,默认情况下是非公平的。2 使用示例ArrayBlockin...原创 2018-09-27 18:32:47 · 299 阅读 · 0 评论 -
JUC--ReenTrantLock学习(三)源码分析之释放锁
1 概述通过前面一篇文章(JUC--ReenTrantLock学习(二)源码分析之获取锁)我们已经学习了ReenrantLock获取锁的相关知识,这里我们将要学习ReenTrantLock释放锁的内容。下面我们直接开始源码的学习。2 源码分析首先,我们依然来看一下释放锁unlock的调用流程。(1)unlock public void unlock() { ...原创 2018-08-23 16:59:22 · 364 阅读 · 0 评论 -
JUC--AQS源码分析(二)同步状态的获取与释放
1概述上一遍文章JUC--AQS源码分析(一)CLH同步队列我们了解了CLH同步队列的结构,以及同步队列的入列和出列。那么通过这篇文章我们将了解到同步状态的获取和释放。当然这里针对同步状态的获取和释放就需要区分共享模式和独占模式。通过查看AQS的源码我们可以发现AQS中使用了模板方法模式(针对模板方法模式我们可以查看Java设计模式--模板方法模式)。AQS提供了大量的模板方法,主要分成三...原创 2018-08-15 11:48:29 · 564 阅读 · 0 评论 -
JUC--AQS源码分析(三)阻塞和唤醒线程
1 概述上一篇文章 JUC--AQS源码分析(二)同步状态的获取与释放,我们学习到了同步状态的获取与释放的源码,并且对线程的阻塞和唤醒有了一个初步的了解,这里我们进行深一步的分析。2 阻塞我们知道在获取线程同步状态失败的时候,会将线程加入到CLH同步队列,并且进行自旋等待。而在自旋等待方法acquireQueued中我们可以看见需要再次进行获取同步状态,如果获取同步状态失败则需要判断当...原创 2018-08-17 10:57:53 · 605 阅读 · 0 评论 -
java高并发--线程状态和创建线程
一、线程的生命状态我们查看Thread.State类可以发现,线程的生命状态分成NEW,RUNNABLE,BLOCKED,WAITING,TIME_WATING,TEMINATED几种状态,这几种状态的具体含义如下。(1)NEW:这种状态表示线程刚刚创建,还没有开始执行,那么什么时候才开始执行呢?等到调用start()方法的时候线程就开始执行了。在这里需要注意的是只要线程经过了NEW状态就原创 2017-09-23 09:16:14 · 289 阅读 · 0 评论 -
Java线程池详解
1 概述在我们工作中,通常需要创建一些线程来处理一些业务,最常用的就是记录系统日志,这个时候如果我们手动创建线程,比如采用最传统的方式,那么这个时候就会出现反复创建很多线程,然后当线程使用完的时候,这些线程又会被关闭,这样就会浪费很多时间来反复创建和销毁线程。那么这个时候就需要我们现在要谈的线程池上场了。使用线程池,我们可以预先创建多条线程,在使用的时候不再需要我们去创建,而是直接从线程池...原创 2017-10-10 22:34:37 · 328 阅读 · 0 评论 -
Java高并发--volatile使用及实现原理
1概述针对sychronized,我们知道它是一个重量级的锁,而我们现在要讨论的volatile就是一个轻量级的,不会引起线程切换。在我们讨论volatile的原理之前,我们先来看看Java多线程的一些概念。2Java多线程的可见性、原子性、有序性(1)可见性可见性是指多个线程的情况下,一个线程改变了一个变量的值,而另外的线程能够马上看见这个值得改变。为什么能实现这种功能呢?因为在...原创 2017-10-01 07:30:51 · 2133 阅读 · 0 评论 -
Java高并发--等待线程结束和谦让
针对本格专题我们主要讨论join()和yield()这两个方法。一、等待线程结束如果我们想要在一个线程中获取到另外一个线程的处理结果,那么 这个时候我们该怎么办呢?最好的方式当然就是等待另一个线程的结束后再来执行当前线程,这个时候就该我们的join()方法上场了。注意:这个方法一共有两个重载方法,传入了时间参数的重载方法表示等待固定的时间,如果在等待的时间结束后等待的线程还没有执行完,原创 2017-09-27 07:22:47 · 1088 阅读 · 0 评论 -
Java高并发--等待通知和挂起继续执行
一、等待通知但我们在使用多线程的时候,通常会遇到线程执行到某一个点的时候需要停止下来,等待其他线程执行,当其他线程执行到某一个点的时候,当前线程再来执行的情况。针对这种情况,我们就需要使用到wait()和notify()两个方法了,这两个方法分别是线程等待和唤醒线程。但是我们要注意的一个点就是,这两个方法并不是线程API提供了,而是Object类提供的。具体的使用方法如下:public原创 2017-09-24 10:28:45 · 1241 阅读 · 1 评论 -
Java高并发--停止线程和中断线程
一、停止线程在java中如果想要停止一个线程,我们可以使用stop()方法,但是建议最好不要只用这个方法,因为这个方法会破坏数据的一致性。那么为什么会发生这种情况呢?因为在我们调用Thread.stop()方法的时候,会释放掉线程持有的锁,而这个锁就是保持线程一致性的关键。下面我们将使用一个例子来展示调用Thread.stop()带来的后果。/** * 终止线程 * * @aut原创 2017-09-23 16:09:24 · 389 阅读 · 0 评论 -
JUC--CountDownLatch源码分析(基于JDK1.8)
1 概述前面一篇文章()我们对CountDownLatch进行了简单的介绍,并对CountDownLatch的使用使用了例子展示,那么这一篇文章我们就要来看一看CountDownLatch底层到地是怎么实现的。2 UML类图注意上图仅仅展现了类关系,针对类内部的结构没有进行展示,从上面我们可以猜测CountDownLatch的内部功能的实现又和AQS这个玩意脱不了干系,多半又是通过...原创 2018-08-27 17:28:03 · 324 阅读 · 0 评论 -
JUC--CountDownLatch简介和使用
1 概述在我们的项目开发当中,我们通常会遇到这样的问题,一个线程的执行要等到其余几个线程执行完成才能开始,这种情况我们怎么办呢?这里就可以使用到我们JUC下面的并发工具类CountDownLatch。2 示例import java.util.Random;import java.util.concurrent.CountDownLatch;import java.util.co...原创 2018-08-27 10:19:36 · 347 阅读 · 0 评论 -
JUC--AQS源码分析(一)CLH同步队列
1 概述了解过JUC的源码,我们就可以知道JUC下面很多工具的实现都是依靠AQS,而AQS中用于保存等待线程的队列就是CLH。CLH是一个FIFO的队列。队列的每一个节点都是一个Node对象。当前线程获取同步状态失败的时候就会进入CLH队列。而当同步状态被释放的时候会通知首节点再次去获取同步状态。2 Node节点首先我们来看看Node节点的实现到底是怎么回事,源码如下:stati...原创 2018-08-13 14:29:27 · 1103 阅读 · 0 评论 -
Java高并发--ThreadLocal使用及源码分析
1概述线程本地变量(ThreadLocal)位每一个线程创建一个变量副本,从而线程就可以单独使用自己拥有的变量副本,而相互之间不产生影响。而线程本地变量与线程同步机制中的共享变量有什么区别呢?很明显,每个线程对共享变量的修改对于其余线程是可见的,而每个线程对线程本地变量的修改对于其余线程是不可见的。2示例package com.liutao.concurrent;public c...原创 2018-07-24 13:49:57 · 318 阅读 · 0 评论 -
Java高并发--原子变量
1 概述原子变量最主要的一个特点就是所有的操作都是原子的,synchronized关键字也可以做到对变量的原子操作。只是synchronized的成本相对较高,需要获取锁对象,释放锁对象,如果不能获取到锁,还需要阻塞在阻塞队列上进行等待。而如果单单只是为了解决对变量的原子操作,建议使用原子变量。关于原子变量的介绍,主要涉及以下内容:原子变量的基本概念 通过AtomicInteger了...原创 2018-07-11 11:44:22 · 318 阅读 · 0 评论 -
JAVA锁、CAS、AQS
一、为什么要用锁?锁-是为了解决并发操作引起的脏读、数据不一致的问题。二、锁实现的基本原理2.1、volatileJava编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便。volatile在多处理器开发中保证了共享变量的“ 可见性”。可见性的意思是当一个线程修改一个共享变量时...原创 2018-04-13 11:00:52 · 291 阅读 · 0 评论