在开发服务器端软件项目时,软件经常需要处理执行时间很短而数目却非常巨大的请求,如果为每一个请求创建一个新的线程,会导致性能上的瓶颈,因为线程对象的创建和销毁需要JVM频繁地进行处理,如果请求的执行时间很短,可能花在创建和销毁线程对象的时间大于真正执行任务的时间,若这样,则系统性能大幅降低。

在JDK5中提供了线程池的支持,主要的作用是支持高并发的访问处理,并且可以将程对象进行复用,核心原理即创建了一个运行效率比较优异的线程池,在中支持线程对象管理,包括创建与销毁,使用池时只需要执行具体的任务即可,线程对象处理都在池中被封装了。

首先看一下:Executor接口,如下图所示:

executor.png

上图其实分为两条主线,下面这个图说的更清楚:

Executor.jpg

第一条主线是:Executor接口->ExecutorService子接口->AbstractExecutorService抽象类->ThreadPoolExecutor类,参数过多,出现工厂类->Executors工厂类
第一条主线是:Executor接口->ExecutorService子接口->ScheduledExecutorService类->ScheduledThreadPoolExecutor类->Executors工厂类

Executor接口是Executor框架的一个最基本的接口,Executor框架的大部分类都直接或间接地实现了此接口。它只有一个方法
void execute(Runnable command): 在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。
Executor的几种实现原理介绍:
1、 Executor 接口并没有严格地要求执行是异步的。在最简单的情况下,执行程序可以在调用者的线程中立即运行已提交的任务:

 class DirectExecutor implements Executor {
     public void execute(Runnable r) {
         r.run();
     }
 }

2、 更常见的是,任务是在某个不是调用者线程的线程中执行的。以下执行程序将为每个任务生成一个新线程。

class ThreadPerTaskExecutor implements Executor {
     public void execute(Runnable r) {
         new Thread(r).start();
     }
 }

3、 许多 Executor 实现都对调度任务的方式和时间强加了某种限制。以下执行程序使任务提交与第二个执行程序保持连续,这说明了一个复合执行程序。

 class SerialExecutor implements Executor {
     private final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
     private  final Executor executor;
     Runnable active;

     SerialExecutor(Executor executor) {
         this.executor = executor;
     }

     public synchronized void execute(final Runnable r) {
         tasks.offer(new Runnable() {
             public void run() {
                 try {
                     r.run();
                 } finally {
                     scheduleNext();
                 }
             }
         });
         if (active == null) {
             scheduleNext();
         }
     }

     protected synchronized void scheduleNext() {
         if ((active = tasks.poll()) != null) {
             executor.execute(active);
         }
     }

 }