本篇文章为大家展示了Java J.U.C中executors框架的设计理念是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。juc-executors
框架是整个J.U.C包中类/接口关系最复杂的框架,真正理解executors框架的前提是理清楚各个模块之间的关系,高屋建瓴,从整体到局部才能透彻理解其中各个模块的功能和背后的设计思路。网上有太多文章讲executors框架,要么泛泛而谈,要么一叶障目不见泰山,缺乏整体视角,很多根本没有理解整个框架的设计思想和模块关系。本文将对整个executors框架做综述,介绍各个模块的功能和联系,后续再深入探讨每个模块,包括模块中的各个工具类。Executor
是JDK1.5时,随着J.U.C引入的一个接口,引入该接口的主要目的是解耦任务本身和任务的执行。我们之前通过线程执行一个任务时,往往需要先创建一个线程,然后调用线程的start
方法来执行任务:我们可以像下面这样执行任务,而不必关心线程的创建:由于Executor仅仅是一个接口,所以根据其实现的不同,执行任务的具体方式也不尽相同,比如:①同步执行任务DirectExecutor是一个同步任务执行器,对于传入的任务,只有执行完成后execute才会返回。②异步执行任务ThreadPerTaskExecutor是一个异步任务执行器,对于每个任务,执行器都会创建一个新的线程去执行任务。③对任务进行排队执行SerialExecutor 会对传入的任务进行排队(FIFO顺序),然后从队首取出一个任务执行。以上这些示例仅仅是给出了一些可能的Executor实现,J.U.C包中提供了很多Executor的具体实现类,我们以后会具体讲到,这里关键是理解Executor的设计思想——对任务和任务的执行解耦。Executor接口提供的功能很简单,为了对它进行增强,J.U.C又提供了一个名为ExecutorService
接口,ExecutorService也是在JDK1.5时,随着J.U.C引入的:可以看到,ExecutorService继承了Executor,它在Executor的基础上增强了对任务的控制,同时包括对自身生命周期的管理,主要有四类:关闭执行器,禁止任务的提交;监视执行器的状态;提供对异步任务的支持;提供对批处理任务的支持。
*仅当执行器已关闭且所有任务都已经执行完成,才返回true.
*注意:除非首先调用shutdown或shutdownNow,否则该方法永远返回false.
*/
booleanisTerminated();
/**
*阻塞调用线程,等待执行器到达【终止】状态.
*
*@return{@codetrue}如果执行器最终到达终止状态,则返回true;否则返回false
*@throwsInterruptedExceptionifinterruptedwhilewaiting
*/
booleanawaitTermination(longtimeout,TimeUnitunit)throwsInterruptedException;
/**
*提交一个具有返回值的任务用于执行.
*注意:Future的get方法在成功完成时将会返回task的返回值.
*
*@paramtask待提交的任务
*@param
*@return返回该任务的Future对象
*@throwsRejectedExecutionException如果任务无法安排执行
*@throwsNullPointerExceptionifthetaskisnull
*/
/**
*提交一个Runnable任务用于执行.
*注意:Future的get方法在成功完成时将会返回给定的结果(入参时指定).
*
*@paramtask待提交的任务
*@paramresult返回的结果
*@param
*@return返回该任务的Future对象
*@throwsRejectedExecutionException如果任务无法安排执行
*@throwsNullPointerExceptionifthetaskisnull
*/
/**
*提交一个Runnable任务用于执行.
*注意:Future的get方法在成功完成时将会返回null.
*
*@paramtask待提交的任务
*@return返回该任务的Future对象
*@throwsRejectedExecutionException如果任务无法安排执行
*@throwsNullPointerExceptionifthetaskisnull
*/
Future>submit(Runnabletask);
/**
*执行给定集合中的所有任务,当所有任务都执行完成后,返回保持任务状态和结果的Future列表.
*
*注意:该方法为同步方法.返回列表中的所有元素的Future.isDone()为true.
*
*@paramtasks任务集合
*@param
*@return任务的Future对象列表,列表顺序与集合中的迭代器所生成的顺序相同,
*@throwsInterruptedException如果等待时发生中断,会将所有未完成的任务取消.
*@throwsNullPointerException任一任务为null
*@throwsRejectedExecutionException如果任一任务无法安排执行
*/
/**
*执行给定集合中的所有任务,当所有任务都执行完成后或超时期满 香港云主机时(无论哪个首先发生),返回保持任务状态和结果的Future列表.
*/
/**
*执行给定集合中的任务,只有其中某个任务率先成功完成(未抛出异常),则返回其结果.
*一旦正常或异常返回后,则取消尚未完成的任务.
*/
/**
*执行给定集合中的任务,如果在给定的超时期满前,某个任务已成功完成(未抛出异常),则返回其结果.
*一旦正常或异常返回后,则取消尚未完成的任务.
*/
throwsInterruptedException,ExecutionException,TimeoutException;
}
*注意:该方法为同步方法.返回列表中的所有元素的Future.isDone()为true.
*
*@paramtasks任务集合
*@param
*@return任务的Future对象列表,列表顺序与集合中的迭代器所生成的顺序相同,
*@throwsInterruptedException如果等待时发生中断,会将所有未完成的任务取消.
*@throwsNullPointerException任一任务为null
*@throwsRejectedExecutionException如果任一任务无法安排执行
*/
/**
*执行给定集合中的所有任务,当所有任务都执行完成后或超时期满时(无论哪个首先发生),返回保持任务状态和结果的Future列表.
*/
/**
*执行给定集合中的任务,只有其中某个任务率先成功完成(未抛出异常),则返回其结果.
*一旦正常或异常返回后,则取消尚未完成的任务.
*/
/**
*执行给定集合中的任务,如果在给定的超时期满前,某个任务已成功完成(未抛出异常),则返回其结果.
*一旦正常或异常返回后,则取消尚未完成的任务.
*/
throwsInterruptedException,ExecutionException,TimeoutException;
}ScheduledExecutorService
,该接口也是在JDK1.5时,随着J.U.C引入的:ScheduledExecutorService提供了一系列schedule方法,可以在给定的延迟后执行提交的任务,或者每个指定的周期执行一次提交的任务,我们来看下面这个示例:上述示例先创建一个ScheduledExecutorService类型的执行器,然后利用scheduleAtFixedRate方法提交了一个“蜂鸣”任务,每隔10s该任务会执行一次。注意:scheduleAtFixedRate
方法返回一个ScheduledFuture对象,ScheduledFuture其实就是在Future的基础上增加了延迟的功能。通过ScheduledFuture,可以取消一个任务的执行,本例中我们利用schedule方法,设定在1小时后,执行任务的取消。ScheduledExecutorService完整的接口声明如下:至此,Executors框架中的三个最核心的接口介绍完毕,这三个接口的关系如下图:通过第一部分的学习,读者应该对Executors框架有了一个初步的认识,Executors框架就是用来解耦任务本身与任务的执行,并提供了三个核心接口来满足使用者的需求:Executor:提交普通的可执行任务ExecutorService:提供对线程池生命周期的管理、异步任务的支持ScheduledExecutorService:提供对任务的周期性执行支持既然上面三种执行器只是接口,那么就一定存在具体的实现类,J.U.C提供了许多默认的接口实现,如果要用户自己去创建这些类的实例,就需要了解这些类的细节,有没有一种直接的方式,仅仅根据一些需要的特性(参数)就创建这些实例呢?因为对于用户来说,其实使用的只是这三个接口。JDK1.5时,J.U.C中还提供了一个Executors
类,专门用于创建上述接口的实现类对象。Executors其实就是一个简单工厂,它的所有方法都是static的,用户可以根据需要,选择需要创建的执行器实例,Executors一共提供了五类可供创建的Executor执行器实例。Executors提供了两种创建具有固定线程数的Executor的方法,固定线程池在初始化时确定其中的线程总数,运行过程中会始终维持线程数量不变。可以看到下面的两种创建方法其实都返回了一个ThreadPoolExecutor
实例。ThreadPoolExecutor是一个ExecutorService接口的实现类,我们会在后面用专门章节讲解,现在只需要了解这是一种Executor,用来调度其中的线程的执行即可。上面需要注意的是ThreadFactory
这个接口:既然返回的是一个线程池,那么就涉及线程的创建,一般我们需要通过new Thread ()
这种方法创建一个新线程,但是我们可能希望设置一些线程属性,比如
名称、守护程序状态、ThreadGroup 等等,线程池中的线程非常多,如果每个线程都这样手动配置势必非常繁琐,而ThreadFactory 作为一个线程工厂可以让我们从这些繁琐的线程状态设置的工作中解放出来,还可以由外部指定ThreadFactory实例,以决定线程的具体创建方式。Executors提供了静态内部类,实现了ThreadFactory接口,最简单且常用的就是下面这个DefaultThreadFactory:可以看到,DefaultThreadFactory 初始化的时候定义了线程组、线程名称等信息,每创建一个线程,都给线程统一分配这些信息,避免了一个个手工通过new的方式创建线程,又可进行工厂的复用。除了固定线程数的线程池,Executors还提供了两种创建只有单个线程Executor的方法:可以看到,只有单个线程的线程池其实就是指定线程数为1的固定线程池,主要区别就是,返回的Executor实例用了一个FinalizableDelegatedExecutorService
对象进行包装。我们来看下FinalizableDelegatedExecutorService,该类 只定义了一个finalize方法:核心是其继承的DelegatedExecutorService,这是一个包装类,实现了ExecutorService的所有方法,但是内部实现其实都委托给了传入的ExecutorService 实例:有些情况下,我们虽然创建了具有一定线程数的线程池,但出于资源利用率的考虑,可能希望在特定的时候对线程进行回收(比如线程超过指定时间没有被使用),Executors就提供了这种类型的线程池:可以看到,返回的还是ThreadPoolExecutor对象,只是指定了超时时间,另外线程池中线程的数量在[0, Integer.MAX_VALUE]
之间。如果有任务需要延迟/周期调用,就需要返回ScheduledExecutorService接口的实例,ScheduledThreadPoolExecutor
就是实现了ScheduledExecutorService接口的一种Executor,和ThreadPoolExecutor一样,这个我们后面会专门讲解。Fork/Join线程池是比较特殊的一类线程池,在JDK1.7时才引入,其核心实现就是ForkJoinPool
类。关于Fork/Join框架,我们后面会专题讲解,现在只需要知道,Executors框架提供了一种创建该类线程池的便捷方法。至此,Executors框架的整体结构基本就讲解完了,此时我们的脑海中应有大致如下的一幅类继承图:下面来回顾一下,上面的各个接口/类的关系和作用:Executor
执行器接口,也是最顶层的抽象核心接口, 分离了任务和任务的执行。ExecutorService
在Executor的基础上提供了执行器生命周期管理,任务异步执行等功能。ScheduledExecutorService
在ExecutorService基础上提供了任务的延迟执行/周期执行的功能。Executors
生产具体的执行器的静态工厂ThreadFactory
线程工厂,用于创建单个线程,减少手工创建线程的繁琐工作,同时能够复用工厂的特性。AbstractExecutorService
ExecutorService的抽象实现,为各类执行器类的实现提供基础。ThreadPoolExecutor
线程池Executor,也是最常用的Executor,可以以线程池的方式管理线程。ScheduledThreadPoolExecutor
在ThreadPoolExecutor基础上,增加了对周期任务调度的支持。ForkJoinPool
Fork/Join线程池,在JDK1.7时引入,时实现Fork/Join框架的核心类。
上述内容就是Java J.U.C中executors框架的设计理念是什么,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注开发云行业资讯频道。
相关推荐: OpenCV关于万达平台搭建重映射map_x,map_y的疑惑
OpenCV中什么万达平台搭建论坛:haozbbs.com Q1446595067 是重映射就不赘述了,主要是对源码中map_x,map_y有些疑惑,图像是如何进行重映射的呢?上下变换的部分源码:开始看老半天不理解重映射原理,后来把map_x,map_y内的值…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。