Module java.base

Package java.util.concurrent


package java.util.concurrent
在并发编程中通常有用的实用程序类。此包包括一些小型标准的可扩展框架,以及一些提供有用功能的类,否则实现起来会很繁琐或困难。以下是主要组件的简要描述。另请参见java.util.concurrent.locksjava.util.concurrent.atomic包。

执行器

接口。 Executor是一个简单的标准化接口,用于定义自定义类似线程的子系统,包括线程池、异步I/O和轻量级任务框架。根据使用的具体Executor类,任务可以在新创建的线程中执行,现有任务执行线程中执行,或者调用execute的线程中执行,并且可以按顺序或并发执行。 ExecutorService提供了一个更完整的异步任务执行框架。ExecutorService管理任务的排队和调度,并允许受控关闭。 ScheduledExecutorService子接口和相关接口添加了对延迟和周期性任务执行的支持。ExecutorServices提供方法,安排任何表达为Callable的函数的异步执行,这是Runnable的结果承载类比。 Future返回函数的结果,允许确定执行是否已完成,并提供取消执行的方法。 RunnableFuture是一个Future,具有一个run方法,执行后设置其结果。

实现。ThreadPoolExecutorScheduledThreadPoolExecutor提供可调整、灵活的线程池。

Executors提供了最常见种类和配置的Executors的工厂方法,以及一些用于使用它们的实用方法。基于Executors的其他实用程序包括提供Futures的常见可扩展实现的具体类FutureTask,以及协调异步任务组处理的ExecutorCompletionService

ForkJoinPool提供了一个主要设计用于处理ForkJoinTask及其子类实例的Executor。这些类采用工作窃取调度程序,可实现符合在计算密集型并行处理中经常存在的限制的高吞吐量。

队列

ConcurrentLinkedQueue类提供了一个高效可扩展的线程安全非阻塞FIFO队列。 ConcurrentLinkedDeque类类似,但另外支持Deque接口。

java.util.concurrent中的五个实现支持扩展的BlockingQueue接口,定义了put和take的阻塞版本:LinkedBlockingQueueArrayBlockingQueueSynchronousQueuePriorityBlockingQueueDelayQueue。不同的类涵盖了生产者-消费者、消息传递、并行任务处理以及相关并发设计的最常见使用情境。

扩展接口TransferQueue和实现LinkedTransferQueue引入了一个同步的transfer方法(以及相关特性),其中生产者可以选择阻塞等待其消费者。

BlockingDeque接口扩展了BlockingQueue以支持FIFO和LIFO(基于堆栈)操作。类LinkedBlockingDeque提供了一个实现。

时间

TimeUnit类提供了多个粒度(包括纳秒)来指定和控制基于超时的操作。包中的大多数类都包含基于超时的操作,除了无限等待。在使用超时的所有情况下,超时指定方法在指示超时之前应等待的最短时间。实现会尽最大努力尽快检测到超时发生。但是,在检测到超时和线程实际再次执行之间可能会经过无限的时间。所有接受超时参数的方法将小于或等于零的值视为根本不等待。要永久等待,可以使用值Long.MAX_VALUE

同步器

五个类帮助常见的特殊目的同步习语。
  • Semaphore是一个经典的并发工具。
  • CountDownLatch是一个非常简单但非常常见的实用程序,用于阻塞直到给定数量的信号、事件或条件发生。
  • CyclicBarrier是一个可重置的多方同步点,在某些并行编程风格中很有用。
  • Phaser提供了一种更灵活的屏障形式,可用于控制多个线程之间的分阶段计算。
  • Exchanger允许两个线程在会合点交换对象,并在几个管道设计中很有用。

并发集合

除了队列,此包还提供了设计用于多线程上下文中使用的集合实现:ConcurrentHashMapConcurrentSkipListMapConcurrentSkipListSetCopyOnWriteArrayListCopyOnWriteArraySet。当预计许多线程将访问给定集合时,ConcurrentHashMap通常优于同步的HashMapConcurrentSkipListMap通常优于同步的TreeMap。当预计读取和遍历的次数远远超过对列表的更新次数时,CopyOnWriteArrayList优于同步的ArrayList

在此包中某些类使用的“Concurrent”前缀是一种简写,表示与类似的“同步”类有几个不同之处。例如,java.util.HashtableCollections.synchronizedMap(new HashMap())是同步的。但是ConcurrentHashMap是“并发的”。并发集合是线程安全的,但不受单个排除锁的控制。在ConcurrentHashMap的特定情况下,它安全地允许任意数量的并发读取以及大量并发写入。当需要通过单个锁阻止对集合的所有访问时,同步类可能很有用,但会牺牲可伸缩性。在其他情况下,其中多个线程预计将访问共同集合时,“并发”版本通常更可取。当集合未共享或仅在持有其他锁时可访问时,未同步的集合更可取。

大多数并发集合实现(包括大多数队列)还与通常的java.util约定不同,因为它们的迭代器分割器提供弱一致性而不是快速失败的遍历:

  • 它们可以与其他操作同时进行
  • 它们永远不会抛出ConcurrentModificationException
  • 它们保证遍历元素时,元素会按照构造时的状态遍历一次,可能(但不保证)反映构造后的任何修改。

内存一致性属性

《Java语言规范》第17章定义了对共享变量的读写等内存操作的happens-before关系。一个线程的写操作只有在写操作happens-before读操作时,另一个线程的读操作才能保证看到写操作的结果。 synchronizedvolatile构造,以及Thread.start()Thread.join() 方法可以形成 happens-before 关系。具体来说:
  • 线程中的每个操作 happens-before 程序顺序中稍后出现的该线程中的每个操作。
  • 监视器的解锁(synchronized 块或方法退出) happens-before 同一监视器的每个后续锁定(synchronized 块或方法进入)。由于 happens-before 关系是传递的,解锁之前线程的所有操作 happen-before 所有后续锁定该监视器的线程的所有操作。
  • volatile 字段的写入 happens-before 该字段的每个后续读取。对 volatile 字段的写入和读取具有类似于进入和退出监视器的内存一致性效果,但不涉及互斥锁定。
  • 对线程调用 start happens-before 启动线程中的任何操作。
  • 线程中的所有操作 happen-before 任何其他线程成功从该线程的 join 中返回。
java.util.concurrent 及其子包中所有类的方法扩展了这些保证到更高级别的同步。具体来说:
  • 在将对象放入任何并发集合之前线程中的操作 happens-before 在另一个线程中访问或从集合中删除该元素的操作。
  • 在将 Runnable 提交给 Executor 之前线程中的操作 happens-before 其执行开始。对于提交给 ExecutorServiceCallables 也是如此。
  • Future 表示的异步计算中的操作 happens-before 在另一个线程中通过 Future.get() 检索结果的操作。
  • 在“释放”同步器方法(如 Lock.unlockSemaphore.releaseCountDownLatch.countDown)之前的操作 happens-before 在另一个线程中对同一同步器对象的成功“获取”方法(如 Lock.lockSemaphore.acquireCondition.awaitCountDownLatch.await)之后的操作。
  • 对通过 Exchanger 成功交换对象的每对线程,每个线程中的 exchange() 之前的操作 happens-before 另一个线程中相应 exchange() 之后的操作。
  • 在调用 CyclicBarrier.awaitPhaser.awaitAdvance(以及其变体)之前的操作 happens-before 由屏障操作执行的操作,以及屏障操作执行的操作 happens-before 从其他线程的相应 await 成功返回之后的操作。
查看 Java 语言规范:
17.4.5 Happens-before Order
自 JDK 版本:
1.5