Java 并发核心编程(六)

6.3Coordination classes

java.util.concurrent包中有几个类适用于常见的多线程通讯。这几个协作类适用范围几乎涵盖了使用wait/notifyCondition最常见的场景,而且更安全、更易于使用。

CyclicBarrier

CyclicBarrier初始化的时候指定参与者的数量。参与者调用awart()方法进入阻塞状态直到参与者的个数达到指定数量,此时最后一个到达的线程执行预定的屏障任务,然后释放所有的线程。屏障可以被重复的重置状态。常用于协调分组的线程的启动和停止。

CountDownLatch 

需要指定一个计数才能初始化CountDownLatch。线程调用await()方法进入等待状态知道计数变为0。其他的线程(或者同一个线程)调用countDown()来减少计数。如果计数变为0后是无法被重置的。常用于当确定数目的操作完成后,触发数量不定的线程。

Semaphore 

Semaphore维护一个“许可”集,能够使用acquire()方法检测这个“许可”集,在“许可”可用之前Semaphore会阻塞每个acquire访问。线程能够调用release()来返回一个许可。当Semaphore只有一个“许可”的时候,可当做一个互斥锁来使用。

Exchanger

线程在Exchangerexchange()方法上进行交互、原子操作的方式交换数据。功能类似于数据可以双向传递的SynchronousQueue加强版。

7、任务执行

很多java并发程序需要一个线程池来执行队列中的任务。在java.util.concurrent包中为这种类型的任务管理提供了一种可靠的基本方法。

7.1ExecutorService

Executor和易扩展的ExecutorService接口规定了用于执行任务的组件的标准。这些接口的使用者可以通过一个标准的接口使用各种具有不同行为的实现类。

 

最通用的Executor接口只能访问这种类型的可执行(Runnable)任务 :

void execute(Runnable command)

Executor子接口ExecutorService新加了方法,能够执行:Runnable任务、Callable任务以及任务集合。

Future<?> submit(Runnable task)

Future<T> submit(Callable<T> task)

Future<T> submit(Runnable task, T result)

List<Future<T>> invokeAll (Collection<? extends Callable<T>> tasks)

List<Future<T>> invokeAll (Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)

T invokeAny(Collection<? extends Callable<T>> tasks)

T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)

7.2Callable and Future

Callable类似于Runnable,而且能够返回值、抛出异常:

V call() throws Exception;

在一个任务执行框架中提交一个Callable 任务,然后返回一个Future结果是很常见的。Future表示在将来的某个时刻能够获取到结果。Future提供能够获取结果或者阻塞直到结果可用的方法。任务运行之前或正在运行的时候,可以通过Future中的方法取消。

如果只是需要一个Runnable特性的Future(例如在Executor执行),可用使用FutureTaskFutureTask实现了FutureRunnable接口,可用提交一个Runnable类型任务,然后在调用部分使用这个Future类型的任务。

7.3、实现ExecutorService

ExecutorService最主要的实现类是ThreadPoolExecutor。这个实现类提供了大量的可配置特性:

线程池--设定常用线程数量(启动前可选参数)和最大可用线程数量。

线程工厂--通过自定义的线程工厂生成线程,例如生成自定义线程名的线程。

工作队列--指定队列的实现类,实现类必须是阻塞的、可以是无界的或有界的。

被拒绝的任务--当队列已经满了或者是执行者不可用,需要为这些情况指定解决策略。

生命周期中的钩子--重写扩展在任务运行之前或之后的生命周期中的关键点

关闭--停止已接受的任务,等待正在运行的任务完成后,关闭ThreadPoolExecutor

ScheduledThreadPoolExecutorThreadPoolExecutor的一个子类,能够按照定时的方式完成任务(而不是FIFO方式)。在java.util.Timer不是足够完善的情况下,ScheduleThreadPoolExecutor具有强大的可适用性。

 

Executors类有很多静态方法(表10)用于创建适用于各种常见情况的预先包装的ExecutorServiceScheduleExecutorService实例

10

方法

描述

newSingleThreadExecutor

创建只有一个线程的ExecutorService

newFixedThreadPool

返回拥有固定数量线程的ExecutorService

newCachedThreadPool

返回一个线程数量可变的ExecutorService

newSingleThreadScheduledExecutor

返回只有一个线程的ScheduledExecutorService

newScheduledThreadPool

创建拥有一组核心线程的ScheduledExecutorService

 

下面的例子是创建一个固定线程池,然后提交一个长期运行的任务:

在这个示例中提交任务到executor之后,代码没有阻塞而是立即返回。在代码的最后一行调用get()方法会阻塞直到有结果返回。

 

ExecutorService几乎涵盖了所有应该创建线程对象或线程池的情景。在代码中需要直接创建一个线程的时候,可以考虑通过Executor工厂创建的ExecutorService能否实现相同的目标;这样做经常更简单、更灵活。

 

7.4CompletionService

除了常见的线程池和输入队列模式,还有一种常见的情况:为后面的处理,每个任务生成的结果必须积累下来。CompletionService接口允许提交CallableRunnable任务,而且还可以从任务队列中获取这些结果:(绿色部分和英文版不一样,已和作者确认,英文版将take()poll()方法混淆了)

Future<V> take () -- 如果结果存在则获取,否则直接返回

Future<V> poll () -- 阻塞直到结果可用

Future<V> poll (long timeout, TimeUnit unit) -- 阻塞直到timeout时间结束

ExecutorCompletionServiceCompletionService的标准实现类。在ExecutorCompletionService的构成函数中需要一个ExecutorExecutorCompletionService提供输入队列和线程池。

8Hot Tip

热门信息:当设置线程池大小的时候,最好是基于当前应用所运行的机器拥有的逻辑处理器的数量。在java中,可用使用Runtime.getRuntime().availableProcessors()获取这个值。在JVM的生命周期中,可用处理器的数目是可变的。

9、关于作者

Alex MillerTerracotta Inc公司Java集群开源产品的技术负责人,曾在BEA SystemMetaMatrix工作,是MetaMatrix的首席架构师。他对Java、并发、分布式系统、查询语言和软件设计感兴趣。他的tweeter@puredangerbloghttp://tect.puredanger.com,很喜欢在用户组会议中发言。在St. LouisAlexLambda Lounge小组的创建人,Lambda Lounge用户组是为了学习、动态语言、Strange Loop开发会议而创建的。

 

10、翻译后记

开始阅读英文版的时候,并没有觉得文章中有什么晦涩的地方。但是在翻译之后,才发现将文中的意思清楚地表达出来也是个脑力活,有时一句话能够懂得意思,却是很难用汉语表达出来:“只可意会,不可言传”--这也能解释我当年高中作文为啥每次只能拿40分(总分60)。在禅宗,师傅教弟子佛理,多靠弟子自身的明悟,故有当头棒喝、醍醐灌顶之说。做翻译却不能这样,总不能让读者对着满篇的鸟文去琢磨明悟吧,须得直译、意译并用,梳理文字。

翻译也是一个学习的过程。阅读本文的时候会无意忽略自己以为不重要的词句,待到真正翻译的时候,才发现自己一知半解、一窍不通,就只好Google之,翻译完成后,也学了些知识,可谓是一箭双雕。

个人精力所限,翻译中难免有不对的地方,望大家予以指正。

 

11、原文+译文下载地址

http://download.csdn.net/source/2805800

 

 

你可能感兴趣的:(java,设计模式,多线程,编程,Exchange)