CountDownLatch

     它被用来同步一个或多个任务,强制它们等待其他任务运行的一组操作完毕。
     你能够向CountDownLatch对象设置一个初始计数值,不论什么在这个对象上调用await()的方法都将堵塞。直至这个计数值到达0。其他任务在结束其工作时。能够在该对象上调用countDown()来减小这个计数值。

CountDownLatch被设计为仅仅触发一次,计数值不能被重置。假设你须要能够重置值的版本号。则能够使用CylicBarrier。

     调用countDown()的任务在产生这个调用时并没有被堵塞。仅仅有对await()的调用会被堵塞。直至计数值到达0。
     CountDownLatch的典型使用方法是当前程序有n个互相独立的可解决任务。并创建值为n的CountDownLatch。当每一个任务完毕时,都会在这个锁存器上调用countDown()。

等待问题被解决的任务在这个锁存器上调用await()。将它们自己拦住,直到锁存器计数结束。


总结
     CountDownLatch模拟了一种多任务堵塞等待-多可解决任务达成某一条件的这一场景。假设仅仅是多任务堵塞等待某一任务。那么直接使用wait和signalAll就能够简单实现了。假设是等待多任务完毕,使用wait和signalAll就必需要结合一个计数值及锁来共同实现这样的情景。java帮我们抽象出了这样的应用场景,解决方式名为CountDownLatch。

CyclicBarrier

     CyclicBarrier适用于这种情况:你希望创建一组任务,它们并行的运行工作,然后在进行下一个步骤之前等待,直至全部任务都完毕(看起来有些像join())。它使得全部的并行任务都将在栅栏处队列,因此能够一致地向前移动。

总结
     CountDownLatch像有裁判员的田径比赛,要等全部裁判员都到位之后,才干开跑。CyclicBarrier像没有裁判员的比赛。仅仅须要比赛队员各就各位之后就能够直接开跑。试想一下用wait和signal怎样实现这样的场景,利用一个锁来控制一个计数值的訪问,假设这个计数值大于1,就wait到某个对象上(能够是这个计数值对象),然后-1,假设计数值为1,则对该对象signalAll。

java帮我们抽象出这样的场景,名曰CyclicBarrier。


DelayQueue

     这是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,当中的对象仅仅能在其到期时才干从队列中取出。这样的队列是有序的,即队头对象的延迟到期的时间最长。

假设没有不论什么延迟到期,那么就不会有不论什么头元素,而且poll()将返回null(正由于这样,你不能将null放置到这样的队列中)。

     Delayed接口有一个方法名为getDelay(),它能够用来告知延迟到期有多长时间,或者延迟在多长时间之前已经到期,这种方法将限制我们去使用TimeUnit类。     

总结
     对于普通队列来说就是一个先进先出的队列。对于DelayQueue队列的理解能够觉得它存在两个队列。一个优先级队列存放还未到期的任务(从队头到队尾的任务。依据到期时间由近到远排序)。然后依次将到期的任务放入一个有序队列。这个有序队列就是我们真正take时取的队列。

该构件如其名,代表放入该队列的对象自己能够控制自己被取出的时间。

     在使用场景上,DelayQueue适用于限制在多少时间之后才运行的任务。

这里限制它的是时间。而不是其它线程。


PriorityBlockingQueue

     与普通BlockingQueue差别仅在于不以进队列时间评出队列时间,而以优先级高低说了算。一个以时间论英雄,一个以优先级论英雄。


SynchronousQueue

     这是一种没有内部容量的堵塞队列。因此每一个put()都必须等待一个take()。反之亦然。

这就好像是你把一个对象交给某人-没有不论什么桌子能够放置这个对象,因此仅仅有在这个人伸出手,准备好接收这个对象时,你才干工作。


ScheduledExecutor

     ScheduledExecutor提供给你一种能够定期启动线程的方式。你能够使用schedule()(运行一次任务)或者ScheduleAtFixedRate()(每隔规则的时间反复运行任务),你能够将Runnable对象设置为在将来的某个时刻运行。

功能上类似于定时器。在web系统中,使用很频繁。

Semaphore

     正常的锁(来自concurrent.locks或内建的synchronized锁),在不论什么时刻都仅仅同意一个任务訪问一项资源,而计数信号量同意n个任务同一时候訪问这个资源。
     实际上,信号量使用较少:1. 资源訪问大多仅仅存在1到2的差别,不存在2到多的差别,线程安全的对象多个訪问时没有问题,线程不安全的对象两个线程訪问就有问题。 2. 假设当前使用场景是仅仅有n个对象提供服务,能够用信号量实现,实际上用堵塞队列可能是更好的做法。

Exchanger

     Exchanger是在两个任务之间交换对象的栅栏。当这些任务进入栅栏时,它们各自拥有一个对象,当它们离开时,它们都拥有之前由对象持有的对象。

Exchanger的典型应用场景是:一个任务在创建对象。这些对象的生产代价非常高昂。而还有一个任务在消费这些对象。

通过这样的方式,能够有很多其它的对象在创建的同一时候被消费。



漫谈并发编程(六):java中一些经常使用的并发构件的介绍的更多相关文章

  1. Java并发编程:Java中的锁和线程同步机制

    锁的基础知识 锁的类型 锁从宏观上分类,只分为两种:悲观锁与乐观锁. 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新 ...

  2. 【并发编程】Java中的原子操作

    什么是原子操作 原子操作是指一个或者多个不可再分割的操作.这些操作的执行顺序不能被打乱,这些步骤也不可以被切割而只执行其中的一部分(不可中断性).举个列子: //就是一个原子操作 int i = 1; ...

  3. 【并发编程】Java中的锁有哪些?

    0.死锁 两个或者两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞现象,若无外力作用,他们都将无法让程序进行下去: 死锁条件: 不可剥夺条件: T1持有的资源无法被T2剥夺 请 ...

  4. Java并发编程:Java的四种线程池的使用,以及自定义线程工厂

    目录 引言 四种线程池 newCachedThreadPool:可缓存的线程池 newFixedThreadPool:定长线程池 newSingleThreadExecutor:单线程线程池 newS ...

  5. 【并发编程】Java并发编程传送门

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. [并发编程系列博客传送门](https://www.cnblogs.com/54 ...

  6. 为什么函数式编程在Java中很危险?

    摘要:函数式编程这个不温不火的语言由来已久.有人说,这一年它会很火,尽管它很难,这也正是你需要学习的理由.那么,为什么函数式编程在Java中很危险呢?也许这个疑问普遍存在于很多程序员的脑中,作者Ell ...

  7. java编程思想-java中的并发(二)

    二.共享受限资源 有了并发就可以同时做多件事情了.但是,两个或多个线程彼此互相干涉的问题也就出现了.如果不防范这种冲突,就可能发生两个线程同时试图访问同一个银行账户,或向同一个打印机打印,改变同一个值 ...

  8. java编程思想-java中的并发(一)

    一.基本的线程机制 并发编程使我们可以将程序划分为多个分离的.独立运行的任务.通过使用多线程机制,这些独立任务中的每一个都将由执行线程来驱动. 线程模型为编程带来了便利,它简化了在单一程序中同时jia ...

  9. 【Java并发编程六】线程池

    一.概述 在执行并发任务时,我们可以把任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程,只要池里有空闲的线程,任务就会分配一个线程执行.在线程池的内部,任务被插入一个阻塞队列(Blo ...

  10. 多线程编程学习六(Java 中的阻塞队列).

    介绍 阻塞队列(BlockingQueue)是指当队列满时,队列会阻塞插入元素的线程,直到队列不满:当队列空时,队列会阻塞获得元素的线程,直到队列变非空.阻塞队列就是生产者用来存放元素.消费者用来获取 ...

随机推荐

  1. linux定时调度器每秒运行一次

    linux操作系统最小粒度的定时调度器仅仅能调到分钟的级别,工作中有时需在到秒的调度,所以须要自己编写脚本来实现 #!/bin/bash while [ true ]; do /bin/sleep 1 ...

  2. typedef 总结

    其实在正儿八经学C语言的时候typedef用的不是很多,记得书上对它的介绍只是一笔带过.的确它的用法是很简单,但这不代表在使用的过程中不会出错,今天来个彻底的总结. 作用:用来建立新的数据类型名.(注 ...

  3. SpringMVC日期类型转换问题三大处理方法归纳

    方法一:实体类中加日期格式化注解 @DateTimeFormat(pattern = "yyyy-MM-dd") private Date receiveAppTime; 方法二: ...

  4. Web网页中内嵌Activex的Activex插件开发 .

    转载自: http://blog.csdn.net/tttyd/article/details/5258096 源代码下载 http://files.cnblogs.com/tttyd/Activex ...

  5. 【新提醒】N820 N821 android 4.2 V1.1版 - 大V综合交流区 - 360官方论坛

    http://bbs.360safe.com/forum.php?mod=viewthread&tid=3088815&extra=page%3D1%26filter%3Dtypeid ...

  6. perl malformed JSON string, neither tag, array, object, number, string or atom, at character offset

    [root@wx03 ~]# cat a17.pl use JSON qw/encode_json decode_json/ ; use Encode; my $data = [ { 'name' = ...

  7. uva 620 Cellular Structure

    题目连接:620 - Cellular Structure 题目大意:给出一个细胞群, 判断该细胞的可能是由哪一种生长方式的到的, 输出该生长方式的最后一种生长种类, "SIMPLE&quo ...

  8. Linux设备驱动中的ioctl

    memdev.h #ifndef _MEMDEV_H #define _MEMDEV_H #define MEM_MAGIC 'm' #define MEM_RESTART _IO(MEM_MAGIC ...

  9. 恢复PasswordChar 默认值、取消密码框设置

    //三种都是清空 this.textBox1.PasswordChar = new char(); this.textBox1.PasswordChar = '\0'; this.textBox1.P ...

  10. linux环境 :Linux 共享库LIBRARY_PATH, LD_LIBRARY_PATH 与ld.so.conf

    参考: 1. Linux 共享库:LD_LIBRARY_PATH 与ld.so.conf Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径.(该路径在默 ...