Java并发简介
Java平台包括一个并发实用程序包。 这些类被设计用来作为构建并发类或应用程序的构建块。 正如集合框架通过提供常用数据结构的实现来简化内存中数据的组织和操作一样,并发实用程序通过提供并发设计中常用的构建块的实现,来简化并发类的开发。 并发实用程序包括高性能、灵活的线程池;异步执行任务的框架;一组为并发访问而优化的集合类;同步实用程序,如计数信号量;原子变量、锁和条件变量。
使用并发实用程序,而不是自己开发线程池之类的组件,可以提供许多优势:
-
减少了编程工作。
使用一个标准类要比自己开发它容易。
-
增加性能。
并发实用程序中的实现由并发和性能专家开发并进行同行评审;即使是熟练的开发人员,这些实现也可能比典型的实现更快、更具可伸缩性。
-
增加可靠性。
开发并发类很困难——Java语言提供的底层并发原语(synchronized、volatile、wait()、notify()和notifyAll()很难正确使用,使用这些工具可能很难检测和调试错误。通过使用标准化的、经过广泛测试的并发构建块,可以消除许多线程危险的潜在来源,如死锁、饥饿、竞争条件或过多的上下文切换。 对并发实用程序进行了仔细的审计,以避免死锁、饥饿和竞争条件。
-
提高可维护性。
使用标准库类的程序比依赖复杂的自定义类的程序更容易理解和维护。
-
增加生产力。
开发人员可能已经了解了标准库类,因此不需要学习特殊并发组件的API和行为。此外,当并发应用程序构建在可靠的、经过良好测试的组件上时,调试会更简单。
简而言之,使用并发实用程序实现并发应用程序可以帮助您的程序更清晰、更短、更快、更可靠、更可伸缩、更容易编写、更容易阅读和更容易维护。
并发实用程序包括:
-
任务调度框架( Task scheduling framework)
Executor接口根据一组执行策略对异步任务的调用、调度、执行和控制进行标准化。 提供的实现支持让任务可以在单个后台线程(如Swing中的事件)、新创建的线程或线程池中的线程上被执行,开发人员可以创建支持任意执行策略的Executor的自定义实现。 内置的实现提供了可配置的策略,比如队列长度限制和拒绝策略,可以通过防止资源使用失控来提高应用程序的稳定性。
-
Fork / join框架。( Fork/join framework)
基于ForkJoinPool类,这个框架是Executor的实现。它的设计目的是使用工作线程池高效地运行大量任务。工作窃取技术用于保持所有工作线程处于繁忙状态,以充分利用多个处理器。
-
并发集合( Concurrent collections)
添加了几个新的集合类,包括新的Queue、BlockingQueue和BlockingDeque接口,以及Map、List和Queue的高性能并发实现。
-
原子变量( Atomic variables)
提供了实用程序类,可以原子地操作单个变量(基本类型或引用),提供高性能的原子算法和 compare-and-set 方法。java.util.concurrent.atomic 中的原子变量实现,提供了比使用同步(在大多数平台上)更高的性能,这使得它们对于实现高性能并发算法和方便地实现计数器和序列号生成器非常有用。
-
同步器( Synchronizers)
通用同步类,包括信号量(semaphores)、屏障(barriers)、锁存器( latches)、相量(phasers)和交换器(exchangers),促进了线程之间的协调。
-
锁( Locks)
虽然锁定是通过synchronized关键字构建到Java语言中的,但是内置的监视锁有许多限制。java.util.concurrent.locks包提供了一个高性能的锁与相同的内存语义实现同步,它还支持试图获得一个锁时指定超时,一个锁多个条件变量,嵌套( "hand-over-hand")持有多个锁,并支持线程正在等待获取锁时中断线程。
-
纳秒粒度计时( Nanosecond-granularity timing.)
System.nanoTime方法允许访问纳秒粒度的时间源,以便进行相关的时间测量和接受超时的方法(例如 BlockingQueue.offer, BlockingQueue.poll, Lock.tryLock, Condition.await, 和 Thread.sleep)接受以纳秒为单位的超时值。System.nanoTime实际精度是平台相关的。