执行器的高级特性
执行器是一个类,它允许编程人员执行并发任务而无须担心线程的创建和管理。
执行器框架具有以下基本特征。
-
如何创建执行器以及在创建执行器时有哪些不同选项。
- 如何将并发任务发送给执行器。
- 如何控制执行器使用的资源。
- 在执行器的内部,如何使用一个线程池优化应用程序的性能。
任务的撤销
将任务发送给执行器之后,还可以撤销该任务的执行。
使用 submit() 方法将 Runnable 对象发送给执行器时,它会返回 Future 接口的一个实现。
该类允许你控制该任务的执行。该类有 cancel()方法,可用于撤销任务的执行。
该方法接收一个布尔值作为参数,如果接收到的参数为 true ,那么执行器执行该任务,否则执行该任务的线程会被中断。
以下便是想要撤销的任务无法被撤销的情形。
-
任务已经被撤销。
- 任务已经完成了执行。
- 任务正在执行而提供给 cancel() 方法的参数为 false 。
- 在 API 文档中并未说明的其他原因。
cancel() 方法返回了一个布尔值,用于表明当前任务是否被撤销。
任务执行调度
ThreadPoolExecutor 类是 Executor 接口和 ExecutorService 接口的基本实现。
但是 Java并发 API为该类提供了一个扩展类,以支持预定任务的执行,这就是 ScheduledThreadPoolExeuctor 类。
可以进行如下操作。
-
在某段延迟之后执行某项任务。
-
周期性地执行某项任务,包括以固定速率执行任务或者以固定延迟执行任务。
重载执行器方法
执行器框架是一种非常灵活的机制。
可以通过扩展一个已有的类( ThreadPoolExecutor 或者 ScheduledThreadPoolExecutor )实现自己的执行器,获得想要的行为。
如果重载了 ThreadPoolExecutor 类,就可以重载以下方法。
-
beforeExecute() :
该方法在执行器中的某一并发任务执行之前被调用。
它接收将要执行的 Runnable 对象和将要执行这些对象的 Thread 对象。
该方法接收的 Runnable 对象是 FutureTask 类的一个实例,而不是使用 submit() 方法发送给执行器的 Runnable 对象。 - afterExecute() :
该方法在执行器中的某一并发任务执行之后被调用。
它接收的是已执行的 Runnable 对象和一个 Throwable 对象,该 Throwable 对象存储了任务中可能抛出的异常。
与 beforeExecute() 方法相同, Runnable 对象是 FutureTask 类的一个实例。 - newTaskFor() :
该方法创建的任务将执行使用 submit() 方法发送的 Runnable 对象。
该方法必须返回 RunnableFuture 接口的一个实现。
默认情况下,Open JDK 9 和 Oracle JDK 9 返回 FutureTask 类的一个实例,但是这在今后的实现中可能会发生变化。
如果扩展 ScheduledThreadPoolExecutor 类,你可以重载 decorateTask() 方法。
该方法与面向预定任务的 newTaskFor() 方法类似并且允许重载执行器所执行的任务。
更改一些初始化参数
可以在执行器创建之时更改一些参数以改变其行为。
最常用的一些参数如下所示。
-
**BlockingQueue
** : 每个执行器均使用一个内部的 BlockingQueue 存储等待执行的任务。 可以将该接口的任何实现作为参数传递。 例如,更改执行器执行任务的默认顺序。 - ThreadFactory :
可以指定 ThreadFactory 接口的一个实现,而且执行器将使用该工厂创建执行该任务的线程。
例如,你可以使用 ThreadFactory 接口创建 Thread 类的一个扩展类,保存有关任务执行时间的日志信息。 - RejectedExecutionHandler :
调用 shutdown() 方法或者 shutdownNow() 方法之后,所有发送给执行器的任务都将被拒绝。
可以指定 RejectedExecutionHandler 接口的一个实现管理这种情形。