Executor是一个多线程管理框架,创建线程的方式有三种Thread、Runnable、Callable。但是如果用这三种方式创建线程则存在线程的生命周期管理困难,无限创建线程的话还会存在资源消耗(内存消耗高)、线程生命周期的开销过高(cpu计算资源的消耗)、系统稳定性问题(不同系统创建线程的数量限制不同包括JVM的启动参数、Thread构造函数请求的栈大小、底层操作系统对线程数量的限制)。
Executor是一个基于生产者和消费者模式的接口。主要做了以下几件事:
1、为灵活和强大的异步任务执行框架提供了基础功能,
2、提供了对生命周期的支
3、统计信息收集、应用程序管理机制和性能监视等机制,其配置是一次性的一般在部署阶段完成。
Executor是为应用程序提供服务的,并会将关闭操作中受影响的任务的状态反馈给应用程序。并且也是可以关闭的。
Executor采用的是两阶段处理方式:将任务的提交和执行解耦开来,通过调用Executors中的静态工厂方法创建线程池:定长线程池(newFixThreadPool)、缓存线程池(newCachedThreadPool)、定时线程池(newScheduledThreadPool)、单一线程池(newSingleThreadPool)。
为了解决线程生命周期的管理问题,ExecutorService接口扩展了Executor,添加了管理生命周期的方法:
public interface ExecutorService extends Executor{ void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedExecption; }
ExecutorService的生命周期有三种状态:1、运行 2、关闭 3、已终止,分别对应着创建时的状态、shutdown和shutdownNow()的关闭状态和awaitTermination的状态。
了解了ExecutorService是对Executor框架的扩展以及其作用以后再接着看Executor中的任务,在Executor框架中任务的生命周期分为四种:创建、提交、开始、完成,并用Future来表示任务的生命周期,并提供相关方法判断任务是否完成和取消。
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return the computed result * @throws CancellationException if the computation was cancelled * @throws ExecutionException if the computation threw an * exception * @throws InterruptedException if the current thread was interrupted * while waiting * @throws TimeoutException if the wait timed out */ V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
在get方法中存在状态依赖,如果任务已经完成则get就会返回结果或者抛出异常,如果任务还在执行则get方法会被阻塞。且如果任务抛出异常则在get方法中会进行一次包装,将异常包装成ExecutionException抛出,并通过getCause()方法来获取被封装的初始异常,如果任务被取消了则会抛出CancellationException,但在java8中这个异常被取消了(原因有待查询)
在Executor中有两种任务表现形式:
<T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task);
Runnable作为基本的任务表现形式但存在一些局限性,这些局限性和Runnable自身相关,即不能返回一个值也不能抛出异常。
Callable弥补了Runable的缺点:可以返回一个值也能抛出异常。
对于需要返回值的任务用Callable这样的表示形式,不需要抛异常和无返回值的用Runnable这样的表现形式。
在这里还需要注意异常的处理方式,有一篇不错的博文可以看看,是关于submit提交方式和execute提交任务对异常的处理方式。
java多线程中的异常处理_进化的深山猿-CSDN博客_cancellationexception怎么解决