(Java 多线程系列)Java 线程池(Executor)
线程池简介
线程池是指管理同一组同构工作线程的资源池,线程池是与工作队列(Work Queue)密切相关的,其中在工作队列中保存了所有等待执行的任务。工作线程(Worker Thread)的任务很简单:从工作队列中获取一个任务,执行任务,然后返回线程池并等待下一个任务。
线程池简化了线程管理工作,并且java.util.concurrent提供了一种灵活的线程池实现作为Executor框架的一部分。在Java类库中,任务执行的主要抽象不是Thread,而是Executor。虽然Executor是个简单的接口,但它却为灵活且强大的异步任务执行框架提供了基础,访框架能支持多种不同类型的任务执行策略。它提供了一种标准的方法将任务的提交过程与执行过程解耦出来,并用Runnable来表示任务。
由于Java类库中有Executor来专门用于线程池的管理的类,所以可以用Executor任务执行框架来实现线程池的构建。
Executor基于生产者-消费者模式,提交任务的操作相当于生产者(生成待完成工作单元),执行任务相当于消费者(执行完这个工作单元).基本框架为:
(此图片转载自http://computerdragon.blog.51cto.com/6235984/1212442)
线程池的创建
可以通过调用Executors中的静态工厂方法之一来创建一个线程池:
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池,每当提交一个任务时就创建一个线程,直到达到线程池的最大数量,这时线程池的规模将不会再变化(如果某个线程由于发生的Exception而结束,那么线程池会补充一个新的线程)
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。
Executor的生命周期
Executor的实现通常会创建线程来执行任务,但是JVM只有在所有(非守护)线程全部终止后才会退出,因此,如果无法正确关闭Executor,那么JVM将无法结束。
由于Executor以异步方式来执行任务,因此在任何时候,之前提交任务的状态不是立即可见的。为了解决执行服务的生命周期问题,ExecutorService拓展了Executor接口,添加了一些用于生命周期管理的方法。
public interface ExecutorService extends Executor {
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
//....
}
ExecutorService的生命周期有3种运行状态:运行、关闭和已终止。ExecutorService在初始创建时处于运行状态。shutdown方法将执行平缓的关闭过程:不再接受新的任务,同时等待已经提交的任务执行完成(包括那些还未开始执行的任务)。shutdownNow方法将执行粗暴的关闭过程:它尝试取消所有运行中的任务,并且不再启动运行队列中尚未开始执行的任务。
等所有任务都完成后,ExecutorService将转入终止状态。可以调用awaitTermination()来等待ExecutorService到达终止状态,或者通过来轮询ExecutorService是否已经终止。通过在调用awaitTermination之后会立即调用shutdown,从而产生同步地关闭ExecutorService的效果。
如果要使用Executor,必须将任务表述为一个Runnable。
PS:没有具体使用过,后续使用了再具体添加