Spring对Executor所提供的抽象
Spring的org.springframework.core.task.TaskExecutor接口等同于java.util.concurrent.Executor接口。它存在主要意义在于使用线程池时可以将对JDK 5.0的依赖抽象掉,以便在不同版本的JDK中都可以享受线程池执行任务这份饕餮大餐。该接口和JDK 5.0的Executor接口拥相同的execute(Runnable task)方法。TaskExecutor拥有一个SchedulingTaskExecutor子接口,新增了任务调度规则定制的功能。
在Spring发行包中预定义了一些TaskExecutor实现。它们可以满足大部分应用要求,一般情况下,你不必自行编写实现类。下面,是TaskExecutor的实现类:
● SyncTaskExecutor:位于org.springframework.core.task包中,实现了TaskExecutor接口。这个实现不会异步执行任务,相反,每次调用都在发起调用的主线程中执行;
下面是SchedulingTaskExecutor的实现类:
●SimpleAsyncTaskExecutor:位于org.springframework.core.task包中。这个实现没有使用线程池,在每次执行任务时都创建一个新线程。但是,它还是支持对并发总数设限,当超过线程并发总数限制时,阻塞新的任务直到有可用的资源;
●ConcurrentTaskExecutor:位于org.springframework.scheduling.concurrent包中。该类是JDK 5.0的Executor的适配器,以便将JDK 5.0的Executor的当成Spring的TaskExecutor使用;
●SimpleThreadPoolTaskExecutor:位于org.springframework.scheduling.quartz包中,这个类实际上是继承于Quartz的 SimpleThreadPool类的子类,它将监听Spring的生命周期回调。当你有线程池,需要在Quartz和非Quartz组件中共用时,该类可以发挥它的用处;
●ThreadPoolTaskExecutor:位于org.springframework.scheduling.concurrent包中。这个实现类只能在JDK 5.0中使用,它暴露的一些属性,方便在Spring中配置一个java.util.concurrent.ThreadPoolExecutor,并把它包装成TaskExecutor;
●TimerTaskExecutor:位于org.springframework.scheduling.timer包中。该类使用一个Timer作为其后台的实现;
上一小节代码清单 10的ExecutorExample只能在JDK 5.0下运行,如果我们用Spring的TaskExecutor替换①处的Executor,当程序需部署到低版本JDK环境中时,仅需要选择一个合适的实现就可以了。
如果我们将ExecutorExample配置成一个Bean,通过注入的方式提供executor属性,就可以方便地选用不同的实现版本。如在JDK 5.0上,你可以选用ThreadPoolTaskExecutor,而在JDK低版本中则可以使用SimpleAsyncTaskExecutor。这样,程序就可以在不同版本的JDK的移植。package com.baobaotao.executor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
public class ExecutorExample ...{
private TaskExecutor executor; ①使用Spring的TaskExecutor替换JDK 5.0的Executor
public void setExecutor(TaskExecutor executor) ...{
this.executor = executor;
}
public void executeTasks() ...{
for (int i = 0; i < 6; i++) ...{
executor.execute(new SimpleTask("task" + i));
}
}
public static void main(String[] args) ...{
ExecutorExample ee = new ExecutorExample();
ee.setExecutor(new SimpleAsyncTaskExecutor());②使用Spring的TaskExecutor实现类
ee.executeTasks();
}
}
class SimpleTask implements Runnable ...{
…
}
小结
对于大量并发的短小型任务,使用线程池进行任务的调度可以带来明显的好处:节省资源、增强伸缩性、获得更快的响应速度。JDK 5.0新增加了支持线程池的Executor,Spring考虑到应用程序在不同版本JDK之间的移植问题,通过TaskExecutor对Executor进行了抽象,这样当应用部署到不同版本JDK时,仅需选择适合的实现类就可以了
