前面主要分析ThreadPoolExecutor类的创建和运行过程,今天学习Executors类。
1.Executors类和Executor类的关系
- Executor是含有执行提交Runnable任务的接口。如果你看了关于ThreadPoolExecutor类的分析,那么就知道线程池间接实现Executor接口。
- Executors是一个工厂类,它能提供各种形式的线程池。
2.Executors类的作用
创建以下线程池和执行器。
2.1 newFixedThreadPool
创建一个线程池,该线程池重用在共享无界队列上运行的固定数量的线程。在任何时候,大多数nThreads线程都是活动的处理任务。如果在所有线程都处于活动状态时提交其他任务,它们将在队列中等待,直到线程可用为止。如果任何线程在关闭之前的执行过程中由于失败而终止,那么如果需要执行后续任务,则会替换一个新线程。池中的线程将一直存在,直到显式地执行execuorservice #shutdown关机。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
注意看到核心线程数和最大线程数都为nThreads,表明线程池内自始至终可用线程数为nThread;如果线程池内线程数已经达到nThreads,那么新到达的Runnable任务直接放入等待队列,由于不会再新建线程,所以为了保证池的可用性就使用无界等待队列。
注意提供重载的方法,提供自定义的线程工厂。
2.2 newCachedThreadPool
创建一个线程池,该线程池根据需要创建新线程,但在可用时将重用以前构造的线程。这些池通常会提高执行许多短期异步任务的程序的性能。如果可用,要执行的调用将重用以前构造的线程。如果没有可用的现有线程,将创建一个新线程并将其添加到池中。未使用60秒的线程将被终止并从缓存中删除。因此,长时间空闲的池不会消耗任何资源。注意,可以使用ThreadPoolExecutor构造函数创建具有相似属性但不同细节(例如超时参数)的池。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ExecutorService