转载自 http://www.cnblogs.com/skywang12345/p/java_threads_category.html

JUC:java.util.concurrent

一,JUC原子类

根据修改的数据类型,可以将JUC包中的原子操作类可以分为4类。

1. 基本类型: AtomicInteger, AtomicLong, AtomicBoolean ;

2. 数组类型: AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray ;

3. 引用类型: AtomicReference, AtomicStampedRerence, AtomicMarkableReference ;

4. 对象的属性修改类型: AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater 。

这些类存在的目的是对相应的数据进行原子操作。所谓原子操作,是指操作过程不会被中断,保证数据操作是以原子方式进行的。基本思想都是使用unsafe类的CAS函数实现原子操作的。

比较并交换(compare and swap, CAS),是原子操作的一种,可用于在多线程编程中实现不被打断的数据交换操作,从而避免多线程同时改写某一数据时由于执行顺序不确定性以及中断的不可预知性产生的数据不一致问题。 该操作通过将内存中的值与指定数据进行比较,当数值一样时将内存中的数据替换为新的值。

AtomicLong:

AtomicLong是作用是对长整形进行原子操作。

在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。

示例:

packagecom.util.concurrent.atomic;importjava.util.concurrent.atomic.AtomicLong;public classAtomicLongTest {public static voidmain(String[] args) {//TODO Auto-generated method stub

AtomicLong mAtoLong= newAtomicLong();

mAtoLong.set(0x0123456789ABCDEFL);

System.out.println("toString()" +mAtoLong.toString());

System.out.println("get()" +mAtoLong.get());

System.out.println("intValue()" +mAtoLong.intValue());

System.out.println("longValue()" +mAtoLong.longValue());

System.out.println("incrementAndGet()" +mAtoLong.incrementAndGet());

System.out.println("getAndIncrement()" +mAtoLong.getAndIncrement());

System.out.println("decrementAndGet()" +mAtoLong.decrementAndGet());

System.out.println("getAndDecrement()" +mAtoLong.getAndDecrement());

System.out.println("get()" +mAtoLong.get());

System.out.println("addAndGet()" + mAtoLong.addAndGet(0x10));

System.out.println("getAndAdd()" + mAtoLong.getAndAdd(0x10));

System.out.println("getAndSet()" + mAtoLong.getAndSet(0x0123456789ABCDEEL));

System.out.println("compareAndSet()" + mAtoLong.compareAndSet(0x0123456789ABCDEEL, 0x0123456789ABCDEDL));

System.out.println("get()" +mAtoLong.get());

}

}

结果:

toString()81985529216486895get()81985529216486895intValue()-1985229329longValue()81985529216486895incrementAndGet()81985529216486896getAndIncrement()81985529216486896decrementAndGet()81985529216486896getAndDecrement()81985529216486896get()81985529216486895addAndGet()81985529216486911getAndAdd()81985529216486911getAndSet()81985529216486927compareAndSet()trueget()81985529216486893

AtomicLongArray:

AtomicLong的作用是对长整型进行原子操作,而AtomicLongArray的作用是对长整型数组进行原子操作。

示例:

packagecom.util.concurrent.atomic;importjava.util.concurrent.atomic.AtomicLongArray;public classAtomicLongArrayTest {public static voidmain(String[] args) {//TODO Auto-generated method stub

long[] longArray = new long[] {10, 20, 30, 40, 50};

AtomicLongArray array= newAtomicLongArray(longArray);

System.out.println("array:" + array.get(3));

System.out.println("array.addAndGet:" + array.addAndGet(3, 8));

System.out.println("array.incrementAndGet:" + array.incrementAndGet(3));

System.out.println("array.decrementAndGet:" + array.decrementAndGet(4));

System.out.println("array.getAndIncrement:" + array.getAndIncrement(2));

System.out.println("array.getAndDecrement:" + array.getAndDecrement(1));

System.out.println("array.getAndDecrement:" + array.getAndSet(3, 9));

}

}

结果:

array:40array.addAndGet:48array.incrementAndGet:49array.decrementAndGet:49array.getAndIncrement:30array.getAndDecrement:20array.getAndDecrement:49

AtomicReference:

AtomicReference是作用是对"对象"进行原子操作。

packagecom.util.concurrent.atomic;importjava.util.concurrent.atomic.AtomicReference;public classAtomicReferenceTest {public static voidmain(String[] args) {//TODO Auto-generated method stub

Person p1= new Person(101);

Person p2= new Person(102);

AtomicReference ap = new AtomicReference(p1);

ap.compareAndSet(p1, p2);

Person p3=ap.get();

System.out.println("p3 is " +p3);

System.out.println("p3.equals(p1)=" +p3.equals(p1));

System.out.println("p3.equals(p2)=" +p3.equals(p2));

}

}classPerson {volatile longid;public Person(longid) {this.id =id;

}publicString toString() {return "id:" +id;

}

}

结果:

p3 is id:102p3.equals(p1)=falsep3.equals(p2)=true

AtomicLongFieldUpdater:

AtomicLongFieldUpdater可以对指定"类的 'volatile long'类型的成员"进行原子更新。它是基于反射原理实现的。

示例:

packagecom.util.concurrent.atomic;importjava.util.concurrent.atomic.AtomicLongFieldUpdater;public classAtomicLongFieldUpdaterTest {public static voidmain(String[] args) {//TODO Auto-generated method stub

Class cls= Person2.class;

AtomicLongFieldUpdater updater= AtomicLongFieldUpdater.newUpdater(cls, "id");

Person2 person= new Person2(1234567l);

updater.compareAndSet(person,1234567l, 7654321l);

System.out.println("id:" +person.getId());

}

}classPerson2 {volatile longid;public Person2(longid) {this.id =id;

}public void setId(longid) {this.id =id;

}public longgetId() {returnid;

}publicString toString() {return "id:" +id;

}

}

结果:

id:7654321

二,JUC锁

同步锁:

即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁。Java 1.0版本中就已经支持同步锁了。

同步锁的原理是,对于每一个对象,有且仅有一个同步锁;不同的线程能共同访问该同步锁。但是,在同一个时间点,该同步锁能且只能被一个线程获取到。这样,获取到同步锁的线程就能进行CPU调度,从而在CPU上执行;而没有获取到同步锁的线程,必须进行等待,直到获取到同步锁之后才能继续运行。这就是,多线程通过同步锁进行同步的原理!

JUC包中的锁:

相比同步锁,JUC包中的锁的功能更加强大,它为锁提供了一个框架,该框架允许更灵活地使用锁,只是它的用法更难罢了。

JUC包中的锁,包括:Lock接口,ReadWriteLock接口,LockSupport阻塞原语,Condition条件,AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer三个抽象类,ReentrantLock独占锁,ReentrantReadWriteLock读写锁。由于CountDownLatch,CyclicBarrier和Semaphore也是通过AQS来实现的;因此,我也将它们归纳到锁的框架中进行介绍。

先看看锁的框架图,如下所示。

ReentrantLock

ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”。

ReentrantLock锁在同一个时间点只能被一个线程所持有;可重入的意思是,ReentrantLock可以被单个线程多次获取。ReentrantLock分为“公平锁”和“非公平锁”。它们的区别体现在获取锁的机制上是否公平,ReentraantLock是通过一个FIFO的等待队列来管理获取该锁所有线程的。在“公平锁”的机制下,线程依次排队获取锁;而“非公平锁”在锁是可获取状态时,不管自己是不是在队列的开头都会获取锁。

示例:

packagecom.util.concurrent;importjava.util.concurrent.locks.Condition;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;public classReentrantLockTest {public static voidmain(String[] args) {//TODO Auto-generated method stub

Depot mDepot = newDepot();

Producer2 mPro= newProducer2(mDepot);

Customer2 mCus= newCustomer2(mDepot);

mPro.produce(60);

mPro.produce(120);

mCus.consume(90);

mCus.consume(150);

mPro.produce(110);

}

}classDepot {private int size; //仓库的实际数量

private Lock lock; //独占锁

publicDepot() {this.size = 0;this.lock = newReentrantLock();

}public void produce(intval) {

lock.lock();try{

size+=val;

System.out.printf("%s produce(%d) --> size=%d\n",

Thread.currentThread().getName(), val, size);

}finally{

lock.unlock();

}

}public void consume(intval) {

lock.lock();try{

size-=val;

System.out.printf("%s consume(%d)

Thread.currentThread().getName(), val, size);

}finally{

lock.unlock();

}

}

};//生产者

classProducer2 {privateDepot depot;publicProducer2(Depot depot) {this.depot =depot;

}//消费产品:新建一个线程向仓库中生产产品。

public void produce(final intval) {newThread() {public voidrun() {

depot.produce(val);

}

}.start();

}

}//消费者

classCustomer2 {privateDepot depot;publicCustomer2(Depot depot) {this.depot =depot;

}//消费产品:新建一个线程从仓库中消费产品。

public void consume(final intval) {newThread() {public voidrun() {

depot.consume(val);

}

}.start();

}

}

结果:

Thread-0 produce(60) --> size=60Thread-1 produce(120) --> size=180Thread-2 consume(90) size=50

因为不符合实际情况,出现了size = -60的情况,所以需要加condition来作限定。

importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;importjava.util.concurrent.locks.Condition;//LockTest3.java//仓库

classDepot {private int capacity; //仓库的容量

private int size; //仓库的实际数量

private Lock lock; //独占锁

private Condition fullCondtion; //生产条件

private Condition emptyCondtion; //消费条件

public Depot(intcapacity) {this.capacity =capacity;this.size = 0;this.lock = newReentrantLock();this.fullCondtion =lock.newCondition();this.emptyCondtion =lock.newCondition();

}public void produce(intval) {

lock.lock();try{//left 表示“想要生产的数量”(有可能生产量太多,需多此生产)

int left =val;while (left > 0) {//库存已满时,等待“消费者”消费产品。

while (size >=capacity)

fullCondtion.await();//获取“实际生产的数量”(即库存中新增的数量)//如果“库存”+“想要生产的数量”>“总的容量”,则“实际增量”=“总的容量”-“当前容量”。(此时填满仓库)//否则“实际增量”=“想要生产的数量”

int inc = (size+left)>capacity ? (capacity-size) : left;

size+=inc;

left-=inc;

System.out.printf("%s produce(%3d) --> left=%3d, inc=%3d, size=%3d\n",

Thread.currentThread().getName(), val, left, inc, size);//通知“消费者”可以消费了。

emptyCondtion.signal();

}

}catch(InterruptedException e) {

}finally{

lock.unlock();

}

}public void consume(intval) {

lock.lock();try{//left 表示“客户要消费数量”(有可能消费量太大,库存不够,需多此消费)

int left =val;while (left > 0) {//库存为0时,等待“生产者”生产产品。

while (size <= 0)

emptyCondtion.await();//获取“实际消费的数量”(即库存中实际减少的数量)//如果“库存”

int dec = (size

size-=dec;

left-=dec;

System.out.printf("%s consume(%3d)

Thread.currentThread().getName(), val, left, dec, size);

fullCondtion.signal();

}

}catch(InterruptedException e) {

}finally{

lock.unlock();

}

}publicString toString() {return "capacity:"+capacity+", actual size:"+size;

}

};//生产者

classProducer {privateDepot depot;publicProducer(Depot depot) {this.depot =depot;

}//消费产品:新建一个线程向仓库中生产产品。

public void produce(final intval) {newThread() {public voidrun() {

depot.produce(val);

}

}.start();

}

}//消费者

classCustomer {privateDepot depot;publicCustomer(Depot depot) {this.depot =depot;

}//消费产品:新建一个线程从仓库中消费产品。

public void consume(final intval) {newThread() {public voidrun() {

depot.consume(val);

}

}.start();

}

}public classLockTest3 {public static voidmain(String[] args) {

Depot mDepot= new Depot(100);

Producer mPro= newProducer(mDepot);

Customer mCus= newCustomer(mDepot);

mPro.produce(60);

mPro.produce(120);

mCus.consume(90);

mCus.consume(150);

mPro.produce(110);

}

}

结果:

Thread-0 produce( 60) --> left= 0, inc= 60, size= 60Thread-1 produce(120) --> left= 80, inc= 40, size=100Thread-2 consume( 90) left= 10, inc=100, size=100Thread-3 consume(150) left= 0, inc= 10, size= 10Thread-3 consume(150) left= 0, inc= 80, size= 80Thread-3 consume(150)

java concurrent int_Java高级特性系列--Concurrent相关推荐

  1. 深入理解java虚拟机 -- jVM高级特性与最佳实践

    <深入理解 Java 虚拟机–JVM高级特性与最佳实践> 关于这本书已经断断续续的看了好几遍了,使自己对jvm有了很深的理解,但是由于长时间的不用,对很多的功能点有所遗忘,特此写下这篇随手 ...

  2. 《深入理解Java虚拟机 - Jvm高级特性与最佳实践(第三版)》阅读笔记

    <深入理解Java虚拟机>阅读笔记 本repository为<深入理解Java虚拟机 - Jvm高级特性与最佳实践(第三版)>阅读笔记,因为第一章主要讲的是Java的发展历史, ...

  3. 深入理解java虚拟机 - jvm高级特性与最佳实践(第三版)_JVM虚拟机面试指南:年薪30W以上高薪岗位需求的JVM,你必须要懂!...

    JVM的重要性 很多人对于为什么要学JVM这个问题,他们的答案都是:因为面试.无论什么级别的Java从业者,JVM都是进阶时必须迈过的坎.不管是工作还是面试中,JVM都是必考题.如果不懂JVM的话,薪 ...

  4. java优先队列_Java高级特性增强-多线程

    请戳GitHub原文: https://github.com/wangzhiwubigdata/God-Of-BigData 大数据成神之路系列: 请戳GitHub原文: https://github ...

  5. java 类的高级特性_java程序-类的高级特性

    创建Employee类,在类中定义三个属性:编号,姓名,年龄,然后在构造方法里初始化这三个属性,最后在实现接口中的定义的CompareTo方法,将对象按编号升序排列. 代码如下:(程序可能有些错误,方 ...

  6. 深入理解java虚拟机 - jvm高级特性与最佳实践(第三版)_深入理解Java虚拟机,JVM高级特性与最佳实践!...

    第一部分 走进Java 第二部分 自动内存管理机制 第三部分 虚拟机执行子系统 参考资料: 书籍,网站资源 Java不仅仅是一门编程语言,还是一个由一系列计算机软件和规范形成的技术体系,这个技术体系提 ...

  7. .net java 泛型_Java高级特性泛型看这一篇就够了

    作者:qwer1030274531 出自:ITPUB博客 1.为什么我们需要泛型? 通过两段代码就可以知道为什么需要泛型 /*** * 没有泛型的时候实现加法 */public class NonGe ...

  8. java高级反射_Java高级特性之反射

    老规矩我们还是先提出几个问题,一门技术必然要能解决一定的问题,才有去学习掌握它的价值 一. 什么是反射? 二.反射能做什么? 一. 什么是反射? 用在Java身上指的是我们可以于运行时加载.探知.使用 ...

  9. Java面向对象和高级特性 项目实战(一)

    一.项目简介 项目名:嗖嗖移动业务大厅 技能点: 二.技能点 三.系统概述 四.整体开发思路 五.实体类和接口开发 六. 创建工具类 七.使用集合存储数据 八.开发计划 九.代码实现 1.项目目录 2 ...

最新文章

  1. 物联网兴起 嵌入式系统安全日益受关注
  2. Linux上安装jdk并配置环境变量
  3. Leetcode 122. 买卖股票的最佳时机 II 解题思路及C++实现
  4. char和varchar的区别以及尾部空格问题 - sqlserver演示
  5. python实现文件上传预览_Python文件上传功能简单实现
  6. 数据分析实例(股票分析实例)
  7. java使用POI jar包读写xls文件
  8. NetBeans 7.4 Beta提示警告无效的异常处理
  9. mysql存储过程套嵌_mysql存储过程套嵌
  10. Windows平台RTMP推送摄像头对接介绍
  11. 客户端级别的渲染分析工具 dynaTrace
  12. 数据的表示方法和运算方法
  13. LLVM PASS类pwn题入门
  14. 二进制转换八进制图解_二进制如何转换成八进制?
  15. 【中医学】11 常见病证-1:感冒:咳嗽:泄泻:水肿:淋证:心痛
  16. centos漏洞系列(三):Google Android libnl权限提升漏洞
  17. Redis(九)Redis的过期时间操作以及部分常用命令
  18. 有关数据库sql语句基础小白初学者可学(持续更新)
  19. 华为荣耀8x云相册不见了_华为手机相册图片凭空消失
  20. 福建省莆田市谷歌卫星地图下载

热门文章

  1. (三)设置Jenkins为MLOps构建CI/CD管道
  2. 使用TensorFlow.js在浏览器中进行深度学习入门
  3. 如何搜索旅行的好地方(MongoDb LINQ和.NET Core)
  4. Visual Studio Online 终于公开上线了
  5. 编辑器eslint格式_VScode格式化代码,开启ESlint代码检测方法,eslint代码配置
  6. 台达vfd一ⅴe变频说明书_PLC运动控制实例解析:PLC与变频器系统
  7. word 代码_怎样在Word 中插入 C/C++ 代码
  8. 小程序组件的使用(三) 调用子组件方法
  9. gc日志一般关注什么_JVM(23)JVM的Full GC日志
  10. 连接工作组计算机用户名和密码,访问局域网中工作组的电脑需要用户名和密码...