在应用程序中,总是会出现大量的任务,包括相同类型的和不同类型的。要快速处理这些任务,常见方法就是利用多线程,但是也不可能为每个任务都创建一个线程,这样内存也不够,并且线程的创建销毁开销很大。最好是少量线程处理大量任务,实现线程的复用,Executor干的就是这事。程序只需要把任务提交给Executor,由Executor来确定怎么来执行这个任务,即执行策略。Executor的关闭很重要,如果Executor如果没有关闭,那JVM将无法结束。关闭方法有shutdown,shutdownNow,shutdown方法执行平缓关闭,若该任务没有提交则拒绝提交,若该任务已经提交但是没有执行,将等待它执行完成,若该任务已经执行将等待它执行完成。shutdownNow是粗暴关闭,取消现在执行的任务,拒绝处理新任务,不再启动线程池队列中已提交的任务。当所有已经提交到Executor的任务都执行完成时,Executor将进入terminatede终止状态。

线程池的底层原理:数据结构:线程池管理器(ThreadpoolFactory),worker,任务队列Blockqueue;线程池的调度:新提交一个任务时,所有看下现有的线程数量是不是达到了corepoolSize,如果没有将新建一个线程thread,该线程将执行该任务,当该任务执行完成时,它会去任务队列中取出任务然后执行任务。若当前线程的数量大于corepoolSize小于maxpoolSize,则看下任务队列是否已经满了,若满了则新建线程thread,若没有满则将任务丢到任务队列中。

任务的取消和关闭

建设一个任务执行到一半,程序想取消这个任务,那怎么办呢?最好的方法是由每个任务自己来决定如何取消自己,这将保持数据的一致性,不会乱。常见的方法是轮询一个取消标志位,当该标志位被设立了,则执行自己的取消策略。这种方式会有个弊端,当执行该任务的线程由于某种原因被阻塞掉,那它将看不到标志位的设立,这个时候将加入中断Interrupted。当调用Thread.interrupted()时,线程的中断标志位会被设立,阻塞方法会检查中断标志位,将发现中断标志位为true时,将结束阻塞,重置中断位,提前返回并抛出中断异常。中断处理策略:抛出异常(我不想管了,谁爱管谁管),捕获异常(管了就不能无作为),恢复中断位(我想管,我告诉别人我是要中断的)。说了这么多如何管理任务的生命周期,最后发现Future已经提供了任务的周期的管理抽象,尴尬。对于不可中断的阻塞方法(同步io,Selector.select()方法,获取内置锁)通过中断不能达到取消任务的效果,只能特殊处理,比如说关闭socket.close(),抛出中断异常。当一个线程执行任务时,任务抛出一个未受检异常。jvm将捕获到异常,并终止线程,但是对于Executor这样的服务来说,终止一个线程可能会使它产生影响,所以它捕获异常并新增一条工作者线程(具体是新增还是不管看当前的线程数)。虽然这看起来好像没什么问题,但是这对于程序来说却显的莫名其妙,一个任务无声无息就取消了。针对这种情况提供了一个UncaughtExceptionHandler异常捕获器,线程池可以为每个线程配一个异常捕获器(通过线程池管理器实现)。

Executor以及线程池的更多相关文章

  1. 多线程-Executors和Executor,线程池

    jdk1.5之前,所有的线程都是需要自己手动创建的,由jvm销毁,当请求过多的时候,频繁的创建和销毁线程是非常浪费资源的.jdk1.5为此做了优化,提供了 java.util.concurrent 包 ...

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

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

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

    上一篇文章中通过引入的一个例子介绍了在Executor框架下,提交一个任务的过程,这个过程就像我们老大的老大要找个老大来执行一个任务那样简单.并通过剖析ExecutorService的一种经典实现Th ...

  4. Java 并发 —— Thread、Executor、线程池

    Java 线程池: ThreadPoolExecutor,创建此线程池的方法: new Executors.newCachedThreadPool():尽量避免使用,其无法控制线程数量, Schedu ...

  5. 启用Executor初始化线程池

    前言 上文我们介绍了JDK中的线程池框架Executor.我们知道,只要需要创建线程的情况下,即使是在单线程模式下,我们也要尽量使用Executor.即: ExecutorService fixedT ...

  6. Java并发编程的艺术(十一)——Executor与线程池

    Executor框架简介 从JDK5开始,把工作单元和执行机制分离开来了,工作的单元包括Runnable和Callable,执行机制就是由Executor框架提供. Executor两级调度模型 Ho ...

  7. JAVA Executor(线程池)框架

    一.Executor概述 为更好控制线程,jdk提供一套线程管理框架Executor,帮助开发人员有效地进行线程控制.它们都位于java.util.concurrent包中,是jdk并发包的核心.其中 ...

  8. Java 并发编程中的 Executor 框架与线程池

    Java 5 开始引入 Conccurent 软件包,提供完备的并发能力,对线程池有了更好的支持.其中,Executor 框架是最值得称道的. Executor框架是指java 5中引入的一系列并发库 ...

  9. 2,Executor线程池

    一,Executor框架简介 在Java 5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.co ...

随机推荐

  1. 一张图理解RACSignal的Subscription过程

    通过下面一张图理解RACSignal的调用过程: 创建signale RACSignal通过子类[RACDynamicSignal createSignal:]方法获得Signal,并将disSubs ...

  2. 【转】Nutch的Hadoop方式爬取效率优化

    原文地址:http://my.oschina.net/junfrank/blog/290404

  3. Android学习总结(一)——Activity的基本概念与Activity的生命周期

    一.Activity的基本概念 Activity是Android的四大组件之一,它是一种可以包含用户界面的组件,主要用于和用户进行交互,比如打电话,照相,发送邮件,或者显示一个地图!Activity用 ...

  4. TableView 多余分割线的处理

    方法一,以下两个方法的实现 - (void)viewDidLoad { [super viewDidLoad]; self.tableView.tableFooterView = [[UIView a ...

  5. Java进制转换示例

    收藏的代码,以备查询之用.进制之间转换都是以十进制作为中间层的. int os = 16; //十进制转成十六进制: Integer.toHexString(os); //十进制转成八进制 Integ ...

  6. Oracle 字符集设置

    因为装Linux系统时选择的是英文版,所以当需要测试中文数据库时会出现乱码,这里记录一下我修改字符集的操作. 一些命令: 1.查看sqlplus客户编码: $ echo  $NLS_LANG 2.查看 ...

  7. ASP.NET MVC 5 基本构成

    MVC模式简介: MVC模式两种理解:一种是表现模式,另外一种是架构模式.它将应用程序分成三个主要组件即:视图(View)控件器(Controller)模型(Model) M: Model主要是存储或 ...

  8. mac air 上的Linux命令训练(1)

    1.cat命令 作用: 读取一个文件的全部内容,并将它输出,如果将它输出到一个目标文件,目标文件将会被替换掉. 参数: -n : 加上行号输出 -b:加上行号,但是不加空白行,输出 -s:当遇到多行空 ...

  9. ubuntu firefox上看视频,安装flash啊

    这是针对于直接硬盘安装的linux系统: u盘安装选择了安装第三方软件的话就不会存在这种问题 flash的安装其实也不是很难的,有点耐心就ok了 总结一下: 1:肯定是下载最新版的flash啦,注意看 ...

  10. linux 私房菜 CH6 Linux 的档案权限与目录配置

    查看文件属性 ls -al 第一栏:类型与权限 d:目录: -:档案: l:链接档: b:可随机存取装置: c:一次性存取装置: 第二栏:有多少档名连结到此节点 第三栏:拥有者 第四栏:所属群组 第五 ...