Executor框架简介
Java从JDK5开始,把工作单元与执行机制分离开来。
工作单元包括Runnable和Callable,而执行机制由Executor框架提供。 ----《Java 并发编程的艺术》
Executo框架组成:
-
任务。被执行/调度的任务一般会实现
Runnable
或Callable
接口。 -
任务的执行。任务执行机制的核心接口
Executor
,以及继承自Executor的ExecutorService接口。 Executor框架有两个关键类实现了ExecutorService接口:ThreadPoolExecutor和 ScheduledThreadPoolExecutor.
-
异步计算的结果。包括接口Future和实现Future接口的FutureTask类。
Executor
用于处理被提交的Runnable任务的对象。该接口提供了一种将任务提交与每个任务的运行机制分离的方法,包括线程使用、调用等详细信息。通常使用该接口而不是显示的创建线程。
ExecutorService
实现了接口Executor,提供管理终止的方法和可以生成Future的方法,用于跟踪一个或多个异步任务的进度。可以关闭ExecutorService,这将导致它拒绝新任务。它提供了以下两种不同的方法来关闭ExecutroService。
shutdown()
该方法在终止前都会继续执行以前提交的任务,但是不会保证这些任务都能完成执行。
该方法会使线程池不再接受新的任务。如果线程池已经被关闭那么调用该方法不会造成任何影响。
shutdownNow()
调用该方法,会尝试停止所有正在执行的任务,停止等待任务的处理,并且返回等待执行的任务列表。该方法除了尽力尝试停止执行任务之外,不保证任何事情。例如,该方法的一个典型实现将通过Thread#interrupt 方法停止正在执行任务的线程,因此任何未能响应中断的任务可能永远不会停止。
Executors
Executors工具类,运用了工厂方法模式,提供了创建常见类型线程池的便捷方法。它可以创建4种类型的ThreadPoolExecutor.
FixedThreadPool
拥有固定线程数的线程池。
SingleThreadPool
仅拥有单个线程的线程池,适用于需要保证顺序地执行各个任务;并且任意时间点不会有多个线程是活动的应用场景。
CacheThreadPool
大小无界的的线程池,适合于执行很多的短期任务的小程序。
ScheduledThreadPool
适合于需要多个后台线程执行周期任务,同时为了满足资源管理的需求而需要限制后台线程的数量的应用场景。
线程池的主要处理流程
线程池的使用
一般通过ThreadPoolExecutor来创建一个线程池。
new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,ms,runnableTaskQueue,handler)
-
corePoolSize:线程池的基本大小。如果调用了线程池的prestartAllCoreThreads()方法,线程池会提前创建核心线程。
-
maximumPoolSize:线程池允许创建的最大线程数。如果任务队列已满,并且已创建的线程数少于最大线程数,则线程池会再创建新的线程执行任务。注:如果使用了无界的任务队列则该参数无效果。
-
keepAliveTime:线程活动保持时间。线程池的工作线程空闲后,保持存活的时间。
-
runnableTaskQueue:任务队列,用于保存等待执行的任务的阻塞队列。可以选择以下几个阻塞队列: