并发编程并发队列

2015/03/07 JUC

并发编程并发队列

ConcurrentQueue(并发队列)

阻塞队列解决的问题主要是,当队列达到某临界值时,与之对应的线程被挂起以等待其他线程的唤醒通知,对于这样的场景我们在日常的程序开发中会经常使用到,其有一个非常专业和学术的叫法,即生产者消费者模型(模式)。 https:// en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem 在绝大多数的BlockingQueue中,为了保护共享数据的一致性,需要对共享数据的操作进行加锁处理(显式锁或者synchronized关键字),为了使得操作线程挂起和被唤醒,我们需要借助于对象监视器的wait/notify/notifyAll或者与显式锁关联的Condition。 那么,在Java中有没有一种队列的实现方式可以不用关心临界值的判断,操作该队列的线程也不会被挂起并且等待被其他线程唤醒,我们只是单纯地向该队列中插入或者获取数据,并且该队列是线程安全的,是可以应用于高并发多线程的场景中呢?在JDK1.5版本以前要实现这些要求我们大致有两种方式,具体如下。

  • 通过synchronized关键字对非线程安全的队列或者链表的操作方法进行同步。
  • 使用Collections类的同步方法。 其实第2种方式非常类似于第1种方式,随便打开一个同步方法,源码如下。 ```java …省略 // Collections类的部分源码public static List synchronizedList(List list) { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : new SynchronizedList<>(list)); }

…省略 SynchronizedList(List list) { super(list); this.list = list; } SynchronizedList(List list, Object mutex) { super(list, mutex); this.list = list; } public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) {return list.equals(o);} } public int hashCode() { synchronized (mutex) {return list.hashCode();} } public E get(int index) { synchronized (mutex) {return list.get(index);} } public E set(int index, E element) { synchronized (mutex) {return list.set(index, element);} } public void add(int index, E element) { synchronized (mutex) {list.add(index, element);} } public E remove(int index) { synchronized (mutex) {return list.remove(index);} } ...省略 ``` 这种方式虽然可以确保Collection在多线程环境下的线程安全性,但是synchronized关键字相对于显式锁Lock甚至无锁的实现方式来说效率低下,因此自JDK1.5版本后,Java的开发者们实现了无锁的且线程安全的并发队列实现方案,开发者可以直接借助于它们开发出高性能的应用程序。

  • ConcurrentLinkedQueue:无锁的、线程安全的、性能高效的、基于链表结构实现的FIFO单向队列(在JDK1.5版本中被引入)。
  • ConcurrentLinkedDeque:无锁的、线程安全的、性能高效的、基于链表结构实现的双向队列(在JDK1.7版本中被引入)。

##

Search

    微信好友

    博士的沙漏

    Table of Contents