自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(170)
  • 收藏
  • 关注

原创 Java虚拟机札记-线程安全与锁优化

线程安全什么是线程安全当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是线程安全的。线程安全级别不可变绝对线程安全相对线程安全线程兼容线程对立不可变 不可变的的数据一定是线程安全的。Java语言中,如果共享数据是基

2018-01-24 08:12:35 438 1

原创 Java虚拟机札记-Java内存模型

什么是Java内存模型Java内存模型(Java Memory Model,JMM),是Java虚拟机规范中的定义,用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各个平台下都能达到一致的并发效果。Java内存模型目标定义程序中各个变量的访问规则,比如在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量包括实例字段、静态字段和构成数组对象的元素,

2018-01-23 21:43:43 452

原创 Java虚拟机札记-类加载机制

虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、解析、初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。虚拟机如何加载Class文件?Class文件文件进入内存后是如何形成Java类型的?这就是本文要介绍的内容。在Java语言中,类的加载、连接、初始化都是在程序运行期间完成的,而不是在编译期间完成。这种策略虽然会在类加载时增加一些性能开销,但却大大

2018-01-22 22:02:04 1098

原创 Java虚拟机札记-Class类文件结构

众所周知,Java是与平台无关的。字节码是Java虚拟机实现Java语言平台无关性的基石。Class文件是字节码文件。平台无关性程序的运行不会平台的变化而无法运行或出现运行错误,这样的特性就称为平台无关性。 程序需要在由OS和CPU所构成的平台上运行。每个平台都有自己独特的机器指令,所谓平台的机器指令就是可以被该平台直接识别、执行的一种由0和1组成的序列代码。相同的CPU和不同的OS所

2018-01-21 21:38:19 943

原创 Java虚拟机札记-垃圾回收与内存分配

目前内存分配和垃圾回收已经实现了“自动化”,为什么我们还要关注它们呢?当排查各种内存溢出、内存泄露问题时,当垃圾回收成为提高系统并发量的瓶颈时,有必要对内存的动态分配和垃圾回收进行监控和调节。GC需要考虑三个问题:哪些内存需要回收?什么时候回收?如何回收?哪些内存需要回收?在Java虚拟机札记-Java内存区域划分一文中,我们已经学习了Java运行时内存区域的各个部分。其中,程序计数器...

2018-01-19 22:56:33 1354 1

原创 Java虚拟机札记-Java内存区域划分

众所周知,Java程序员不需要为对象手动分配和释放内存。这要归功于虚拟机。但凡事有利就有弊,一旦出现内存溢出或泄露方面的问题,程序员如果不了解虚拟机是如何管理内存的,排查问题不是件容易的事情。本文将介绍Java虚拟机管理的各个内存区域,为以后学习虚拟机是如何管理内存打好基础。运行时数据区域根据《Java虚拟机规范》,Java虚拟机管理的内存可以分为以下几个运行时数据区域。程序计数...

2018-01-18 22:05:47 1060

原创 Java虚拟机札记-概述

今天开始学习Java虚拟机。本文介绍Java虚拟机的基础知识。JDK与JRE 在学习Java虚拟机之前,我们先来复习下JRE和JDK的定义。JRE,Java Runtime Environment,意为Java运行时环境,包含Java虚拟机和Java API类库。JDK,ava Development Kit ,意为Java开发工具包,包含JRE和Java工具(如编译Java程序的Javac

2018-01-17 22:33:50 1092

原创 Java并发编程札记-总结

一基础01基本概念并发什么是并发并发的优点多线程线程并发与并行线程和进程02创建线程创建线程的方式Thread和Runnable该如何选择run方法与start方法的区别03线程的生命周期线程的生命周期图线程的状态04Thread详解线程等待与唤醒waitnotifynotifyAll线程让步yield线程休眠sleep线程启动start中

2018-01-11 21:42:07 1159 3

原创 Java并发编程札记-(七)JUC工具类-01概述

今天学习JUC中的工具类。CountDownLatch CountDownLatch是一个通用同步器,用于同步一个或多个任务。在完成一组正在其他线程中执行的任务之前,它允许一个或多个线程一直等待。CyclicBarrier CyclicBarrier允许一组线程互相等待,直到到达某个公共屏障点。如果你希望一组并行的任务在下个步骤之前相互等待,直到所有的任务都完成了下个步骤前的所有操

2018-01-07 23:06:07 587

原创 Java并发编程札记-(六)JUC线程池-05ExecutorCompletionService

CompletionService接口是将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者利用submit()提交要执行的任务。使用者利用take()获取并移除已完成的任务的返回值,并按照完成这些任务的顺序处理它们的结果。通常,CompletionService 依赖于一个单独的 Executor 来实际执行任务,在这种情况下,CompletionService 只管理一个内部完成

2018-01-07 21:09:30 480

转载 Java线程池架构2-多线程调度器(ScheduledThreadPoolExecutor)

在前面介绍了java的多线程的基本原理信息:《Java线程池架构原理和源码解析(ThreadPoolExecutor)》,本文对这个java本身的线程池的调度器做一个简单扩展,如果还没读过上一篇文章,建议读一下,因为这是调度器的核心组件部分。我们如果要用java默认的线程池来做调度器,一种选择就是Timer和TimerTask的结合,在以前的文章:《Timer与TimerTask的真正原理&使

2018-01-07 20:10:06 787

转载 聊聊并发(八)——Fork/Join框架介绍

本文首发于InfoQ1. 什么是Fork/Join框架Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。我们再通过Fork和Join这两个单词来理解下Fork/Join框架,Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务

2018-01-06 22:24:43 741

原创 Java并发编程札记-(六)JUC线程池-02ThreadPoolExecutor实现原理

本文通过学习ThreadPoolExecutor源码来学习线程池的实现原理。简介为什么要使用线程池 许多服务器都面临着处理大量客户端远程请求的压力,如果每收到一个请求,就创建一个线程来处理,表面看是没有问题的,但实际上存在着很严重的缺陷。服务器应用程序中经常出现的情况是请求处理的任务很简单但客户端的数目却是庞大的,这种情况下如果还是每收到一个请求就创建一个线程来处理它,服务器在创建和...

2018-01-05 22:02:59 718

原创 Java并发编程札记-(六)JUC线程池-01概述

前面的例子中总是需要线程时就创建,不需要就销毁它。但频繁创建和销毁线程是很耗资源的,在并发量较高的情况下频繁创建和销毁线程会降低系统的效率。线程池可以通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 参考JDK1.8中的相关类,画出下图。 (此图不是十分准确,有些类实现了两个接口,这里只展示出了一个) 本章只是简单地介绍下它们,在以后的文章中会选一些最重要的来学习。Execut

2018-01-04 21:15:41 1865

原创 Java并发编程札记-(五)JUC容器-07ConcurrentLinkedQueue

ConcurrentLinkedQueue是一个基于链表的、无界的、线程安全的队列。此队列按照FIFO原则对元素进行排序。此队列不允许使用null元素。此队列采用了有效的“无等待(wait-free)”算法(CAS算法)。需要小心的是,与大多数collection不同,size方法不是一个固定时间操作。由于这些队列的异步特性,确定当前元素的数量需要遍历这些元素。ConcurrentLink

2018-01-03 21:25:02 722

原创 Java并发编程札记-(五)JUC容器-06LinkedBlockingDeque

LinkedBlockingDeque是一个基于链表的、可指定大小的阻塞双端队列。“双端队列”意味着可以同时从队列的头尾两端同时操作,所以LinkedBlockingDeque既支持FIFO,也支持FILO。可选的容量范围构造方法参数是一种防止过度膨胀的方式。如果未指定容量,那么容量将等于 Integer.MAX_VALUE。只要插入元素不会使双端队列超出容量,每次插入后都将动态地创建链接节点

2018-01-02 16:09:11 468

原创 Java并发编程札记-(五)JUC容器-05ArrayBlockingQueue与LinkedBlockingQueue

ArrayBlockingQueue是一个基于数组的有界阻塞队列。“有界”表示数组容量是固定的。试图向已满队列中放入元素会导致操作受阻塞;试图从空队列中提取元素将导致类似阻塞。此类支持对等待的生产者线程和使用者线程进行排序的可选公平策略。默认情况下,不保证是这种排序。然而,通过将公平性(fairness)设置为true而构造的队列允许按照FIFO顺序访问线程。公平性通常会降低吞吐量,但也减少了可变性

2017-12-29 16:26:23 608 2

原创 Java并发编程札记-(五)JUC容器-04ConcurrentSkipListMap

ConcurrentSkipListMap是线程安全的有序的哈希表。与同是有序的哈希表TreeMap相比,ConcurrentSkipListMap是线程安全的,TreeMap则不是,且ConcurrentSkipListMap是通过跳表(skip list)实现的,而TreeMap是通过红黑树实现的。至于为什么ConcurrentSkipListMap不像TreeMap一样使用红黑树结构,在Con

2017-12-27 21:45:13 478

原创 Java并发编程札记-(五)JUC容器-03ConcurrentHashMap

今天来学习ConcurrentHashMap在JDK1.8中的实现。相比JDK1.7,JDK1.8中ConcurrentHashMap的实现有很大的不同。结构先来看下JDK1.7与JDK1.8中ConcurrentHashMap结构的不同。 JDK1.7结构 在JDK1.7中,ConcurrentHashMap通过“锁分段”来实现线程安全。ConcurrentHashMap将哈希表

2017-12-25 21:44:18 1802

原创 Java并发编程札记-(五)JUC容器-02CopyOnWrite

今天学习CopyOnWriteArrayList。CopyOnWriteArrayList可以看做是线程安全的ArrayList,所有的写操作都是通过对底层数组进行一次新的复制实现的,这种思想称为“写时复制”,CopyOnWriteArrayList的名字也是由此而来。写时复制 CopyOnWrite,简称COW。所谓写时复制,即进行读操作时不加锁以保证性能不受影响,进行写操作时加锁,复制资

2017-12-22 21:56:00 833

原创 Java并发编程札记-(五)JUC容器-01概述

今天开始学习JUC容器。JUC提供了用于多线程上下文中的Collection实现与高效的、可伸缩的、线程安全的非阻塞FIFO队列。参考JDK1.8,画出下图。List JUC容器中List的实现只有CopyOnWriteArrayList。CopyOnWriteArrayList相当于线程安全的ArrayList。Set JUC容器中Set的实现有CopyOnWriteArrayS

2017-12-21 08:04:02 728

原创 Java并发编程札记-(四)JUC锁-10Semaphore简介

一般的锁在任意时刻只允许一个线程访问一项资源,而计数信号量允许n个任务同时访问一项资源。我们可以将信号量看做一个许可集,可以向线程分发使用资源的许可证。获得资源前,线程调用acquire()从许可集中获取许可。该线程结束后,通过release()将许可还给许可集。

2017-12-17 23:31:37 665

原创 Java并发编程札记-(四)JUC锁-09CyclicBarrier

CyclicBarrier允许一组线程互相等待,直到到达某个公共屏障点。如果你希望一组并行的任务在下个步骤之前相互等待,直到所有的任务都完成了下个步骤前的所有操作,才继续向前执行,那么CyclicBarrier很合适。看过CyclicBarrier的方法列表后,有没有发现CyclicBarrier与CountDownLatch比较像。它们之间最大的区别在于CyclicBarrier的计数器可以重置,相当于可以循环使用

2017-12-17 23:30:44 763

原创 Java并发编程札记-(四)JUC锁-08CountDownLatch

CountDownLatch是一个通用同步器,用于同步一个或多个任务。在完成一组正在其他线程中执行的任务之前,它允许一个或多个线程一直等待。可以用一个初始计数值来初始化CountDownLatch对象,任何在这个对象上调用wait()的方法都将阻塞,直至计数值到达0。每完成一个任务,都可以在这个对象上调用countDown()减少计数值。当计数值减为0,所有等待的线程都会被释放。CountDownL

2017-12-17 20:18:24 1025 7

原创 Java并发编程札记-(四)JUC锁-07读写锁的升级—StampedLock

StampedLock是JDK1.8新增的一个锁,是对读写锁ReentrantReadWriteLock的改进。前面已经学习了ReentrantReadWriteLock,我们了解到,在共享数据很大,且读操作远多于写操作的情况下,ReentrantReadWriteLock值得一试。但要注意的是,只有当前没有线程持有读锁或者写锁时才能获取到写锁,这可能会导致写线程发生饥饿现象,即读线程太多导致写线

2017-12-17 19:01:01 1190

原创 Java并发编程札记-(四)JUC锁-06LockSupport

LockSupport是JUC锁中比较基础的类,用来创建锁和其他同步类的基本线程阻塞原语。比如,在AQS中就使用LockSupport作为基本线程阻塞原语。它的park()和unpark()方法分别用于阻塞线程和解除阻塞线程。与Thread.suspend()相比,它没有由于resume()在前发生,导致线程无法继续执行的问题。和Object.wait()对比,它不需要先获得某个对象的锁,能够响应中

2017-12-17 12:38:47 598

原创 Java并发编程札记-(四)JUC锁-05ReentrantReadWriteLock简介

前面在Java并发编程札记-(四)JUC锁-02Lock与ReentrantLock一文中已经学习了ReentrantLock,其中提到了ReentrantLock是互斥锁。与互斥锁相对应的是共享锁。ReadWriteLock就是一种共享锁。ReentrantReadWriteLock是支持与ReentrantLock 类似语义的ReadWriteLock实现。ReadWriteLock维护了

2017-12-16 22:09:21 622

原创 Java并发编程札记-(四)JUC锁-04Condition简介

我们已经学习了如何通过使用锁来同步两个任务,但为了解决某个问题,任务之间只有互斥是不够的,还需要相互通信,相互协作。今天就来学习如何实现任务之间的协作。初识Condition在任务协作中,关键问题是任务之间的通信。握手可以通过Object的监视器方法(wait()和notify()/notifyAll())和synchronized方法和语句来安全地实现。Java SE5的JUC提供了具有

2017-12-16 20:37:48 819

原创 Java并发编程札记-(四)JUC锁-03AQS

AQS,AbstractQueuedSynchronizer的缩写,是JUC中非常重要的一个类。javadoc中对其的介绍是: 为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量、事件,等等)提供一个框架。此类的设计目标是成为依靠单个原子 int 值来表示状态的大多数同步器的一个有用基础。AbstractQueuedSynchronizer是CountDownL

2017-12-11 21:21:06 2936 1

原创 Java并发编程札记-(四)JUC锁-02Lock与ReentrantLock

今天学习Lock与ReentrantLock。Java中的锁有两种,synchronized与Lock。因为使用synchronized并不需要显示地加锁与解锁,所以往往称synchronized为隐式锁,而使用Lock时则相反,所以一般称Lock为显示锁。想了解synchronized更多请移步Java并发编程札记-(一)基础-06synchronized详解。synchronized修

2017-12-09 23:50:29 1049

原创 Java并发编程札记-(四)JUC锁-01概述

今天来学习JUC锁。JUC锁位于java.util.concurrent.locks包下,为锁和等待条件提供一个框架,它不同于内置同步和监视器。参考JDK1.8的java.util.concurrent.locks包,画出如下图: CountDownLatch,CyclicBarrier和Semaphore不在包中,但也是通过AQS来实现的。因此,我也将它们归纳到JUC锁中进行介绍。

2017-12-08 22:17:27 1007

原创 Java并发编程札记-(三)JUC原子类-07CAS

CAS,即compare and swap,比较并交换。CAS操作包含三个操作数:内存值(V),预期值(A)、新值(B)。如果内存值与预期值相同,就将内存值修改为新值,否则不做任何操作。java.util.concurrent.atomic是建立在CAS之上的。下面以AtomicLong为例看下是如何使用CAS的。 下面看下AtomicLong的compareAndSet方法。//

2017-12-07 23:29:54 1073

原创 Java并发编程札记-(三)JUC原子类-06JDK1.8新增:LongAdder、DoubleAdder、LongAccumulator、DoubleAccumulator

DoubleAccumulator、LongAccumulator、DoubleAdder、LongAdder是JDK1.8新增的部分,是对AtomicLong等类的改进。比如LongAccumulator与LongAdder在高并发环境下比AtomicLong更高效。本文以LongAdder为例,学习这些类。API中是这么介绍的:LongAdder中会维护一组(一个或多个)变量,这些变量加起

2017-12-07 22:53:54 4831

原创 Java并发编程札记-(三)JUC原子类-05原子方式更新类的指定volatile字段

AtomicReferenceFieldUpdater、AtomicIntegerFieldUpdater和AtomicLongFieldUpdater是基于反射的实用工具,可以提供对关联字段类型的访问。例如AtomicLongFieldUpdater可以对指定类的指定volatile long字段进行原子更新。本文以AtomicLongFieldUpdater为例来学习。API/

2017-12-07 20:29:08 861

转载 Java并发编程札记-(三)JUC原子类-04原子方式更新引用

提供了引用变量的读写原子性操作。

2017-12-06 20:37:19 779 2

原创 Java并发编程札记-(三)JUC原子类-03原子方式更新数组

今天学习AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray,这几个类的共同特点是都提供数组的原子方式访问和更新功能。下面以AtomicLongArray为代表,对这些类进行介绍。AtomicLongArray可以用原子方式更新其元素的long数组,实例提供long类型数组的原子方式访问和更新功能。API//构造方法摘要

2017-11-28 21:22:02 1165

原创 Java并发编程札记-(三)JUC原子类-02原子方式更新单个变量

今天学习AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference,这几个类的共同特点是都提供单个变量的原子方式访问和更新功能。下面以AtomicLong为代表,对这些类进行介绍。AtomicLong可以看做是用原子方式更新的long值,实例提供long类型单个变量的原子方式访问和更新功能。API//构造方法摘要

2017-11-27 22:44:28 1102

原创 Java并发编程札记-(三)JUC原子类-01概述

今天来学习JUC原子类。JUC原子类位于java.util.concurrent.atomic包下,支持在单个变量上解除锁的线程安全编程。参考JDK1.8的java.util.concurrent.atomic包,画出如下图: 可以将包中的类分为五类:基本类型:AtomicBoolean、AtomicInteger、AtomicLong引用类型:AtomicReference、A

2017-11-27 19:06:02 1309

原创 Java并发编程札记-(二)JUC概述

从今天开始学习JUC。JUC是java.util.concurrent包的简称。下图是JUC的整体结构。1、atomic;2、locks;3、collections;4、threadPool;5、tools

2017-11-23 23:46:21 1322

原创 Java并发编程札记-(一)基础-07volatile详解

volatile同synchronized一样,是Java中实现线程安全的一种机制。与synchronized相比,特点是使用简单、性能高,但容易出错、使用范围有限。《Java语言规范(第三版)》中讲到: Java允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量。Java提供了volatile,在某些情况下比锁更加方便。如果一个字段被声明成volatile,Jav

2017-11-23 21:00:20 1339

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除