java.util.concurrent并发包诸类概览

并发容器

这些容器的关键方法大部分都实现了线程安全的功能,却不使用同步关键字(synchronized)。值得注意的是Queue接口本身定义的几个常用方法的区别,

  1. add方法和offer方法的区别在于超出容量限制时前者抛出异常,后者返回false;
  2. remove方法和poll方法都从队列中拿掉元素并返回,但是他们的区别在于空队列下操作前者抛出异常,而后者返回null;
  3. element方法和peek方法都返回队列顶端的元素,但是不把元素从队列中删掉,区别在于前者在空队列的时候抛出异常,后者返回null。

阻塞队列

  • BlockingQueue.class,阻塞队列接口
  • BlockingDeque.class,双端阻塞队列接口
  • ArrayBlockingQueue.class,阻塞队列,数组实现
  • LinkedBlockingDeque.class,阻塞双端队列,链表实现
  • LinkedBlockingQueue.class,阻塞队列,链表实现
  • DelayQueue.class,阻塞队列,并且元素是Delay的子类,保证元素在达到一定时间后才可以取得到
  • PriorityBlockingQueue.class,优先级阻塞队列
  • SynchronousQueue.class,同步队列,但是队列长度为0,生产者放入队列的操作会被阻塞,直到消费者过来取,所以这个队列根本不需要空间存放元素;有点像一个独木桥,一次只能一人通过,还不能在桥上停留

非阻塞队列

  • ConcurrentLinkedDeque.class,非阻塞双端队列,链表实现
  • ConcurrentLinkedQueue.class,非阻塞队列,链表实现

转移队列

  • TransferQueue.class,转移队列接口,生产者要等消费者消费的队列,生产者尝试把元素直接转移给消费者
  • LinkedTransferQueue.class,转移队列的链表实现,它比SynchronousQueue更快

其它容器

  • ConcurrentMap.class,并发Map的接口,定义了putIfAbsent(k,v)、remove(k,v)、replace(k,oldV,newV)、replace(k,v)这四个并发场景下特定的方法
  • ConcurrentHashMap.class,并发HashMap
  • ConcurrentNavigableMap.class,NavigableMap的实现类,返回最接近的一个元素
  • ConcurrentSkipListMap.class,它也是NavigableMap的实现类(要求元素之间可以比较),同时它比ConcurrentHashMap更加scalable——ConcurrentHashMap并不保证它的操作时间,并且你可以自己来调整它的load factor;但是ConcurrentSkipListMap可以保证O(log n)的性能,同时不能自己来调整它的并发参数,只有你确实需要快速的遍历操作,并且可以承受额外的插入开销的时候,才去使用它
  • ConcurrentSkipListSet.class,和上面类似,只不过map变成了set
  • CopyOnWriteArrayList.class,copy-on-write模式的array list,每当需要插入元素,不在原list上操作,而是会新建立一个list,适合读远远大于写并且写时间并苛刻的场景
  • CopyOnWriteArraySet.class,和上面类似,list变成set而已

 

同步设备

这些类大部分都是帮助做线程之间同步的,简单描述,就像是提供了一个篱笆,线程执行到这个篱笆的时候都得等一等,等到条件满足以后再往后走。

  • CountDownLatch.class,一个线程调用await方法以后,会阻塞地等待计数器被调用countDown直到变成0,功能上和下面的CyclicBarrier有点像
  • CyclicBarrier.class,也是计数等待,只不过它是利用await方法本身来实现计数器“+1”的操作,一旦计数器上显示的数字达到Barrier可以打破的界限,就会抛出BrokenBarrierException,线程就可以继续往下执行;请参见我写过的这篇文章《同步、异步转化和任务执行》中的Barrier模式
  • Semaphore.class,功能上很简单,acquire()和release()两个方法,一个尝试获取许可,一个释放许可,Semaphore构造方法提供了传入一个表示该信号量所具备的许可数量。
  • Exchanger.class,这个类的实例就像是两列飞驰的火车(线程)之间开了一个神奇的小窗口,通过小窗口(exchange方法)可以让两列火车安全地交换数据。
  • Phaser.class,功能上和第1、2个差不多,但是可以重用,且更加灵活,稍微有点复杂(CountDownLatch是不断-1,CyclicBarrier是不断+1,而Phaser定义了两个概念,phase和party),我在下面画了张图,希望能够帮助理解:
    • 一个是phase,表示当前在哪一个阶段,每碰到一次barrier就会触发advance操作(触发前调用onAdvance方法),一旦越过这道barrier就会触发phase+1,这很容易理解;
    • 另一个是party,很多文章说它就是线程数,但是其实这并不准确,它更像一个用于判断advance是否被允许发生的计数器:
      • 任何时候都有一个party的总数,即注册(registered)的party数,它可以在Phaser构造器里指定,也可以任意时刻调用方法动态增减;
      • 每一个party都有unarrived和arrived两种状态,可以通过调用arriveXXX方法使得它从unarrived变成arrived;
      • 每一个线程到达barrier后会等待(调用arriveAndAwaitAdvance方法),一旦所有party都到达(即arrived的party数量等于registered的数量),就会触发advance操作,同时barrier被打破,线程继续向下执行,party重新变为unarrived状态,重新等待所有party的到达;
      • 在绝大多数情况下一个线程就只负责操控一个party的到达,因此很多文章说party指的就是线程,但是这是不准确的,因为一个线程完全可以操控多个party,只要它执行多次的arrive方法。

猜你喜欢

转载自wlt2008-com.iteye.com/blog/2232792