Executor框架详解

java的线程既是工作单元,也是执行机制。从jdk5开始,把工作单元与执行机制分离开来。工作单元包括Runnable和Callable,而执行机制由Executor框架提供。这样一来Executor是基于生产者消费者模式的,提交任务的操作相当于生成者,执行任务的线程相 当于消费者。

一、Executor框架的两级调度模型

在HotSpot VM的模型中,JAVA线程被一对一映射为本地操作系统线程。JAVA线程启动时会创建一个本 地操作系统线程,当JAVA线程终止时,对应的操作系统线程也被销毁回收,而操作系统会调度所有线程 并将它们分配给可用的CPU。

在上层,JAVA程序会将应用分解为多个任务,然后使用应用级的调度器(Executor)将这些任务映射成 固定数量的线程;在底层,操作系统内核将这些线程映射到硬件处理器上。





1、从类图上看,Executor接口是异步任务执行框架的基础,该框架能够支持多种不同类型的任务执行策略。Executor接口就提供了一个执行方法,任务是Runnbale类型,不支持Callable类型。

public interface Executor {
void execute(Runnable command);
}

2、ExecutorService接口实现了Executor接口,主要提供了关闭线程池和submit方法:

public interface ExecutorService extends Executor {
List<Runnable> shutdownNow();
boolean isTerminated();
<T> Future<T> submit(Callable<T> task);
}

另外该接口有两个重要的实现类:ThreadPoolExecutor与ScheduledThreadPoolExecutor。其中ThreadPoolExecutor是线程池的核心实现类,用来执行被提交的任务;而 ScheduledThreadPoolExecutor是一个实现类,可以在给定的延迟后运行任务,或者定期执行命令。

在上一篇文章中,我是使用ThreadPoolExecutor来通过给定不同的参数从而创建自己所需的线程池,但是在后面的工作中不建议这种方式,推荐使用Exectuors工厂方法来创建线程池

Executor框架使用示意图



1、主线程首先要创建实现Runnable或者Callable接口的任务对象工具类Executors,可以把一个Runnable对象封装为一个Callable对象(Executors.callable(Runnable task) 或者 Executors.callable(Runnable task,Object resule))。

2、然后可以把Runnable对象直接交给ExecutorService执行(ExecutorService.execute(Runnable command));或者可以把Runnable对象或Callable对象提交给ExecutorService执行(ExecutorService.submit(Runnable task) 或 ExecutorService.submit(Callable task))。

3、如果执行ExecutorService.submit(…),ExecutorService将返回一个实现Future接口的对象(FutureTask)。由于FutureTask实现了Runnable,程序员也可以创建FutureTask,然后直接交给ExecutorService执行。

4、最后,主线程可以执行FutureTask.get()方法来等待任务执行完成。主线程也可以执行FutureTask.cancel(boolean mayInterruptIfRunning)来取消此任务的执行。

Executor框架的实现ThreadPoolExecutor

Executors可以创建3种类型的ThreadPoolExecutor:SingleThreadExecutorFixedThreadExecutorCachedThreadPool

1、SingleThreadExecutor:单线程线程池

ExecutorService threadPool = Executors.newSingleThreadExecutor();
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}

我们从源码来看可以知道,单线程线程池的创建也是通过ThreadPoolExecutor,里面的核心线程数和线 程数都是1,并且工作队列使用的是无界队列。由于是单线程工作,每次只能处理一个任务,所以后面所 有的任务都被阻塞在工作队列中,只能一个个任务执行。

2、FixedThreadExecutor:固定大小线程池

ExecutorService threadPool = Executors.newFixedThreadPool(5);

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

这个与单线程类似,只是创建了固定大小的线程数量。

3、CachedThreadPool:无界线程池

ExecutorService threadPool = Executors.newCachedThreadPool();

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

无界线程池意味着没有工作队列,任务进来就执行,线程数量不够就创建,与前面两个的区别是:空闲 的线程会被回收掉,空闲的时间是60s。这个适用于执行很多短期异步的小程序或者负载较轻的服务 器。

Executor框架详解的更多相关文章

  1. 跟着阿里p7一起学java高并发 - 第19天:JUC中的Executor框架详解1,全面掌握java并发核心技术

    这是java高并发系列第19篇文章. 本文主要内容 介绍Executor框架相关内容 介绍Executor 介绍ExecutorService 介绍线程池ThreadPoolExecutor及案例 介 ...

  2. java高并发系列 - 第20天:JUC中的Executor框架详解2之ExecutorCompletionService

    这是java高并发系列第20篇文章. 本文内容 ExecutorCompletionService出现的背景 介绍CompletionService接口及常用的方法 介绍ExecutorComplet ...

  3. Executor 框架详解

    框架最核心的类是ThreadPoolExecutor,它是Java线程池的实现类,通过Executors工具类,可以创建3种类型的ThreadPoolExecutor: 首先附上ThreadPoolE ...

  4. mina框架详解

     转:http://blog.csdn.net/w13770269691/article/details/8614584 mina框架详解 分类: web2013-02-26 17:13 12651人 ...

  5. Spark2.1.0——内置Web框架详解

    Spark2.1.0——内置Web框架详解 任何系统都需要提供监控功能,否则在运行期间发生一些异常时,我们将会束手无策.也许有人说,可以增加日志来解决这个问题.日志只能解决你的程序逻辑在运行期的监控, ...

  6. jQuery Validate验证框架详解

    转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...

  7. lombok+slf4j+logback SLF4J和Logback日志框架详解

    maven 包依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lomb ...

  8. [Cocoa]深入浅出 Cocoa 之 Core Data(1)- 框架详解

    Core data 是 Cocoa 中处理数据,绑定数据的关键特性,其重要性不言而喻,但也比较复杂.Core Data 相关的类比较多,初学者往往不太容易弄懂.计划用三个教程来讲解这一部分: 框架详解 ...

  9. iOS 开发之照片框架详解(2)

    一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLib ...

  10. Quartz.NET作业调度框架详解

    Quartz.NET作业调度框架详解 http://www.cnblogs.com/lmule/archive/2010/08/28/1811042.html

随机推荐

  1. nanopi SOCKS5 代理

    nanopi (SOCKS5+openvpn)  +  阿里ES(openvpn + socat) 构建内网代理. 需求: 公网 阿里ES服务器1台,内网nanopi1个(可连接公网服务器), 想从外 ...

  2. nop4.3 admin中添加新菜单

    感觉跟之前版本区别不是很大,先记录下. 1. 首先在sitemap.config 文件里添加菜单. <siteMapNode SystemName="SystemManage" ...

  3. OceanBase使用OBLOADER、OBDUMPER进行导入导出

    需求背景 需要定时给OB进行数据备份,并且在需要时可以全量导入,所以只能通过脚本来减少手动操作的繁琐. 脚本示例 导出脚本 #!/bin/bash # 这一步不能省,如果不设置定时运行时可能会有问题 ...

  4. babel npm包说明

    babel-plugin-import 用于按需加载,在使用antd 的时候引入,可以减少包体积

  5. password_encryption_type 和 pg_hba.conf 不匹配导致用户连不上

    # 问题概述xxx客户新上一套opengauss数据库,在测试中用户输入正确的密码,提示用户密码错误,导致用户被锁# 问题原因password_encryption_type 和 pg_hba.con ...

  6. 洛谷P4342 [IOI1998]Polygon

    题目 https://www.luogu.com.cn/problem/P4342 我会做IOI题辣 思路 算法设计与分析的课堂例题. 首先这是一个环状DP,那么根据老套路,破环成链.发现要求的东西也 ...

  7. PaddleOCR(PaddleHub Serving)离线部署包制作

    PaddleOCR(PaddleHub Serving)离线部署包制作 环境与版本: 系统 CPU架构 Anaconda3 PaddlePaddle PaccleOCR 银河麒麟Server V10 ...

  8. bootstrap-treeview手动修改源码添加与后台交互的id

    bootstrap-treeview中只有自增的参数data-nodeid,没有id的参数,不方便后台交互,修改源码添加id. 1.图一为添加的自定义的node.Id; 2. 下图为添加的id 3.后 ...

  9. connect ETIMEDOUT at PoolConnection.Connection._handleConnectTimeout

    运行 node .\app.js时报错,显示数据库连接超时 此时再运行一次node .\app.js即可

  10. Java数组之冒泡排序【重点】

    冒泡排序 冒泡排序是最为出名的排序算法之一,总共有八大排序! 冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较. 我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2). ...