一、Executor 接口简介

Executor接口是Executor框架的一个最基本的接口,Executor框架的大部分类都直接或间接地实现了此接口。

只有一个方法

void execute(Runnable command): 在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。

Executor的几种实现原理介绍:

1、 Executor 接口并没有严格地要求执行是异步的。在最简单的情况下,执行程序可以在调用者的线程中立即运行已提交的任务:

  1. class DirectExecutor implements Executor {
  2. public void execute(Runnable r) {
  3. r.run();
  4. }
  5. }

2、 更常见的是,任务是在某个不是调用者线程的线程中执行的。以下执行程序将为每个任务生成一个新线程。

  1. class ThreadPerTaskExecutor implements Executor {
  2. public void execute(Runnable r) {
  3. new Thread(r).start();
  4. }
  5. }

3、 许多 Executor 实现都对调度任务的方式和时间强加了某种限制。以下执行程序使任务提交与第二个执行程序保持连续,这说明了一个复合执行程序。

  1. class SerialExecutor implements Executor {
  2. private final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
  3. private final Executor executor;
  4. Runnable active;
  5. SerialExecutor(Executor executor) {
  6. this.executor = executor;
  7. }
  8. public synchronized void execute(final Runnable r) {
  9. tasks.offer(new Runnable() {
  10. public void run() {
  11. try {
  12. r.run();
  13. } finally {
  14. scheduleNext();
  15. }
  16. }
  17. });
  18. if (active == null) {
  19. scheduleNext();
  20. }
  21. }
  22. protected synchronized void scheduleNext() {
  23. if ((active = tasks.poll()) != null) {
  24. executor.execute(active);
  25. }
  26. }
  27. }

二、ExecutorService 接口简介

  ExecutorService 是一个接口,提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成Future 的方法。

ExecutorService 的实现:

  • 三个实现类:AbstractExecutorService(默认实现类) , ScheduledThreadPoolExecutor, ThreadPoolExecutor
  • Executors 提供了此接口的几种常用实现的工厂方法。

方法摘要

1. 从Executor 接口中继承了不跟踪异步线程,没有返回的 execute 方法:

void execute(Runnable command):

在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。

2. 扩展的跟踪异步线程、返回Future 接口的实现类的方法:

Future<?> submit(Runnable task):

提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功 完成时将会返回 null。

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

提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功完成时将会返回给定的结果。

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

提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。该 Future 的 get 方法在成功完成时将会返回该任务的结果。如果想立即阻塞任务的等待,则可以使用 result = exec.submit(aCallable).get(); 形式的构造

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

执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表。返回列表的所有元素的 Future.isDone() 为 true。注意,可以正常地或通过抛出异常来终止已完成 任务。如果正在进行此操作时修改了给定的 collection,则此方法的结果是不确定的。

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

超时等待,同上。

<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException,ExecutionException:

与 invokeAll的区别是,任务列表里只要有一个任务完成了,就立即返回。而且一旦正常或异常返回后,则取消尚未完成的任务。

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

超时等待,同上。

boolean awaitTermination(long timeout,TimeUnit unit) throws InterruptedException:

一直等待,直到所有任务完成。请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行,或者超时时间的到来如果此执行程序终止,则返回 true;如果终止前超时期满,则返回 false

3. 管理生命周期

void shutdown():

启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。

List<Runnable> shutdownNow():

试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。 无法保证能够停止正在处理的活动执行任务,但是会尽力尝试。例如,在 ThreadPoolExecutor 中,通过 Thread.interrupt() 来取消典型的实现,所以如果任务无法响应中断,则永远无法终止。

boolean isShutdown(): 如果此执行程序已关闭,则返回 true。

boolean isTerminated():

如果关闭后所有任务都已完成,则返回 true。注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。

用法示例

下面给出了一个网络服务的简单结构,这里线程池中的线程作为传入的请求。它使用了预先配置的 Executors.newFixedThreadPool(int) 工厂方法:

  1. class NetworkService implements Runnable {
  2. private final ServerSocket serverSocket;
  3. private final ExecutorService pool;
  4. public NetworkService(int port, int poolSize)
  5. throws IOException {
  6. serverSocket = new ServerSocket(port);
  7. pool = Executors.newFixedThreadPool(poolSize);
  8. }
  9. public void run() { // run the service
  10. try {
  11. for (;;) {
  12. pool.execute(new Handler(serverSocket.accept()));
  13. }
  14. } catch (IOException ex) {
  15. pool.shutdown();
  16. }
  17. }
  18. }
  19. class Handler implements Runnable {
  20. private final Socket socket;
  21. Handler(Socket socket) { this.socket = socket; }
  22. public void run() {
  23. // read and service request on socket
  24. }
  25. }

下列方法分两个阶段关闭 ExecutorService。第一阶段调用 shutdown 拒绝传入任务,然后调用 shutdownNow(如有必要)取消所有遗留的任务:

  1. void shutdownAndAwaitTermination(ExecutorService pool) {
  2. pool.shutdown(); // Disable new tasks from being submitted
  3. try {
  4. // Wait a while for existing tasks to terminate
  5. if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
  6. pool.shutdownNow(); // Cancel currently executing tasks
  7. // Wait a while for tasks to respond to being cancelled
  8. if (!pool.awaitTermination(60, TimeUnit.SECONDS))
  9. System.err.println("Pool did not terminate");
  10. }
  11. } catch (InterruptedException ie) {
  12. // (Re-)Cancel if current thread also interrupted
  13. pool.shutdownNow();
  14. // Preserve interrupt status
  15. Thread.currentThread().interrupt();
  16. }
  17. }

参考文献

  • 《java并发编程的艺术》

Executor框架(二)Executor 与 ExecutorService两个基本接口的更多相关文章

  1. java多线程之Executor 与 ExecutorService两个基本接口

    一.Executor 接口简介 Executor接口是Executor框架的一个最基本的接口,Executor框架的大部分类都直接或间接地实现了此接口. 只有一个方法 void execute(Run ...

  2. 详解Executor框架

    在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源.同时,为每一个任务创建一个新线程来执行 ...

  3. Executor框架(一)Executor框架介绍

    Executor框架简介 Executor框架的两级调度模型   在HotSpot VM的线程模型中,Java线程被一对一映射为本地操作系统线程.Java线程启动时会创建一个本地操作系统线程:当Jav ...

  4. 【Java多线程】Executor框架的详解

    在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源.同时,为每一个任务创建一个新线程来执行 ...

  5. 第十章 Executor框架

    在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源.同时,为每一个任务创建一个新线程来执行 ...

  6. java多线程之Executor框架

    Executor框架简介 Executor框架的结构 Executor框架主要由3大部分组成: 任务: 包括被执行的任务需要实现的接口:Runable 接口.Callable接口: 任务的执行: 包括 ...

  7. Java并发(基础知识)—— Executor框架及线程池

    在Java并发(基础知识)—— 创建.运行以及停止一个线程中讲解了两种创建线程的方式:直接继承Thread类以及实现Runnable接口并赋给Thread,这两种创建线程的方式在线程比较少的时候是没有 ...

  8. Java并发和多线程(二)Executor框架

    Executor框架 1.Task?Thread? 很多人在学习多线程这部分知识的时候,容易搞混两个概念:任务(task)和线程(thread). 并发编程可以使我们的程序可以划分为多个分离的.独立运 ...

  9. 戏(细)说Executor框架线程池任务执行全过程(上)

    一.前言 1.5后引入的Executor框架的最大优点是把任务的提交和执行解耦.要执行任务的人只需把Task描述清楚,然后提交即可.这个Task是怎么被执行的,被谁执行的,什么时候执行的,提交的人就不 ...

随机推荐

  1. Mac OS 基于 VirtualEnv 的安装 tensorflow 1.3.0

    如果不行的话,就用conda装吧 https://www.jianshu.com/p/d54546ab315e 推荐使用 virtualenv 创建一个隔离的容器, 来安装 TensorFlow. 这 ...

  2. android中的5大布局

    1.线性布局:LinearLayout layout_margin     上下左右的距离分别为 下面图中的orientation表示的是布局中的方向 分别有horizontal表示水平 vertic ...

  3. CTF之ROT加解密

    常见的ROT加密包括ROT5,ROT13,ROT18,ROT47 ROT5:只是对数字进行编码.用当前数字往后数的第五个数字替换当前数字: 例:123sb——>678sb ROT13:只是对字母 ...

  4. 最小生成树--prim+优先队列优化模板

    prim+优先队列模板: #include<stdio.h> //大概要这些头文件 #include<string.h> #include<queue> #incl ...

  5. hello1与hello2在glassfish上部署

    部署hello1 打开项目实例 找到hello1(tutorial-examples-master\web\jsf\hello1) 并在当前目录打开cmd并输入mvn install命令在hello1 ...

  6. test20181005 序列

    题意 考场30分 维护差值,考虑每次移动的变更,当前2-n位置上的差加1,1位置上的差减n-1. 然后要求的是绝对值的和,用吉司机线段树维护最大最小值.次大次小值. 期望复杂度\(O(n \log n ...

  7. LG1801 【黑匣子_NOI导刊2010提高(06)】

    看到各路dalao用平衡树的做法,表示本人不才,并不会. 然而我会优先队列_huaji_,并且发现用堆解题的dalao们并没有基于在线的做法 于是我的showtime到了 评测结果:https://w ...

  8. hasura 的3factor 架构结论

    hasura 是一个很不错的开发团队,开发了好几款,不错的产品,最近的graphql engine 是很热的一款 graphql 引擎,同时团队提出了3factor 系统架构理论 参考网站 https ...

  9. Oracle 跨库 查询 复制表数据

    在目前绝大部分数据库有分布式查询的需要.下面简单的介绍如何在oracle中配置实现跨库访问. 比如现在有2个数据库服务器,安装了2个数据库.数据库server A和B.现在来实现在A库中访问B的数据库 ...

  10. silverlight 进行本地串口调用的一种可行的解决方法 之silverlight端代码

    接上边的文章. 在javascript暴露操作activex 串口接收之后,就是silverlight端进行串口数据的显示,我们的显示方式比较简单,只是为了演示,我们每隔1秒进行数据的获取并显示, 为 ...