java.util.concurrent 包是专为 Java并发编程
而设计的包。包下的所有类可以分为如下几大类:
脑图地址: http://www.xmind.net/m/tJy5,感谢深入浅出 Java Concurrency ,此脑图在这篇基础上修改而来。
此接口是一个线程安全
的 存取实例
的队列。
BlockingQueue通常用于一个线程生产对象,而另外一个线程消费这些对象的场景。
有限的
,如果队列到达临界点,Thread1
就会阻塞,直到Thread2
从队列中拿走一个对象。Thread2
会阻塞,直到Thread1
把一个对象丢进队列。BlockingQueue中包含了如下操作方法:
Throws Exception | Special Value | Blocks | Times Out | |
---|---|---|---|---|
Insert | add(o) | offer(o) | put(o) | offer(o, timeout, timeunit) |
Remove | remove(o) | poll() | take() | poll(timeout, timeunit) |
Examine | element() | peek() |
remove(o)
来移除任一对象。因为是一个接口,所以我们必须使用一个实现类来使用它,有如下实现类:
见: BlockingQueue
ArrayBlockingQueue 是一个有界的阻塞队列
ArrayBlockingQueue
初始化时的上限。ArrayBlockingQueue
内部以 FIFO(先进先出)
的顺序对元素进行存储。队列中的头元素在所有元素之中是放入时间最久的那个,而尾元素则是最短的那个。DelayQueue 对元素进行持有直到一个特定的延迟到期。注入其中的元素必须实现 java.util.concurrent.Delayed 接口:
public interface Delayed extends Comparable<Delayed< {
public long getDelay(TimeUnit timeUnit); // 返回将要延迟的时间段
}
Delayed
接口也继承了 java.lang.Comparable
接口,Delayed
对象之间可以进行对比。这对DelayQueue
队列中的元素进行排序时有用,因此它们可以根据过期时间进行有序释放。内部以一个链式结构(链接节点)对其元素进行存储 。
一个无界的并发队列,它使用了和类 java.util.PriorityQueue 一样的排序规则。
一个特殊的队列,它的内部同时只能够容纳单个元素。
此接口表示一个线程安全
放入和提取实例的双端队列
。
Throws Exception | Special Value | Blocks | Times Out | |
---|---|---|---|---|
Insert | addFirst(o) | offerFirst(o) | putFirst(o) | offerFirst(o, timeout, timeunit) |
Remove | removeFirst(o) | pollFirst(o) | takeFirst(o) | pollFirst(timeout, timeunit) |
Examine | getFirst(o) | peekFirst(o) |
Throws Exception | Special Value | Blocks | Times Out | |
---|---|---|---|---|
Insert | addLast(o) | offerLast(o) | putLast(o) | offerLast(o, timeout, timeunit) |
Remove | removeLast(o) | pollLast(o) | takeLast(o) | pollLast(timeout, timeunit) |
Examine | getLast(o) | peekLast(o) |
LinkedBlockingDeque 是一个双端队列,可以从任意一端插入或者抽取元素的队列。
一个能够对别人的访问(插入和提取)进行并发处理的 java.util.Map接口。
ConcurrentMap 除了从其父接口 java.util.Map 继承来的方法之外还有一些额外的原子性方法。
因为是接口,必须用实现类来使用它,其实现类为
一个支持并发访问的 java.util.NavigableMap,它还能让它的子 map 具备并发访问的能力。
headMap(T toKey) 方法返回一个包含了小于给定 toKey 的 key 的子 map。
tailMap(T fromKey) 方法返回一个包含了不小于给定 fromKey 的 key 的子 map。
subMap() 方法返回原始 map 中,键介于 from(包含) 和 to (不包含) 之间的子 map。
CountDownLatch 是一个并发构造,它允许一个或多个线程等待一系列指定操作的完成。
CyclicBarrier 类是一种同步机制,它能够对处理一些算法的线程实现同步。
更多实例参考: CyclicBarrier
Exchanger 类表示一种两个线程可以进行互相交换对象的会和点。
更多实例参考: Exchanger
Semaphore 类是一个计数信号量。具备两个主要方法:
- 每调用一次 acquire(),一个许可会被调用线程取走。
- 每调用一次 release(),一个许可会被返还给信号量。
如果你将信号量用于保护一个重要部分,试图进入这一部分的代码通常会首先尝试获得一个许可,然后才能进入重要部分(代码块),执行完之后,再把许可释放掉。
Semaphore semaphore = new Semaphore(1);
//critical section
semaphore.acquire();
...
semaphore.release();
如果你将一个信号量用于在两个线程之间传送信号,通常你应该用一个线程调用 acquire() 方法,而另一个线程调用 release() 方法。
无法担保掉第一个调用 acquire() 的线程会是第一个获得一个许可的线程。
可以通过如下来强制公平:
Semaphore semaphore = new Semaphore(1, true);
这里之前有过简单的总结: Java 中几种常用的线程池
存在于 java.util.concurrent 包里的 ExecutorService 实现就是一个线程池实现。
此接口实现类包括:
Executors.newScheduledThreadPool(10)
创建的其他三种方式
创建的ForkJoinPool 在 Java 7 中被引入。它和 ExecutorService 很相似,除了一点不同。ForkJoinPool 让我们可以很方便地把任务分裂成几个更小的任务,这些分裂出来的任务也将会提交给 ForkJoinPool。
用法参考:Java Fork and Join using ForkJoinPool
Lock 是一个类似于 synchronized 块的线程同步机制。但是 Lock 比 synchronized 块更加灵活、精细。
Lock是一个接口,其实现类包括:
Lock lock = new ReentrantLock();
lock.lock();
//critical section
lock.unlock();
lock() 方法
之后,这个 lock 实例就被锁住啦。读写锁一种先进的线程锁机制。
示例:
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
readWriteLock.readLock().lock();
// multiple readers can enter this section
// if not locked for writing, and not writers waiting
// to lock for writing.
readWriteLock.readLock().unlock();
readWriteLock.writeLock().lock();
// only one writer can enter this section,
// and only if no threads are currently reading.
readWriteLock.writeLock().unlock();
位于 atomic
包下,包含一系列原子性变量。
参考资料: Java 并发工具包 java.util.concurrent 用户指南
java.util.concurrency - Java Concurrency Utilities
扩展阅读:
深入浅出 Java Concurrency : 讲解的很详细