核心提示:一旦企业应用越来越复杂时(比如,基于流程服务器的EIS),它们对相关技术也提出了更高的要求。在使用 EJB 3.0组件技术开发企业应用过程中,它们能够享受到EJB容器提供的线程池、任务调度(@Timeout)服务。现如今,运行于Web容器的Web应用、单独的桌面应用
一旦企业应用越来越复杂时(比如,基于流程服务器的EIS),它们对相关技术也提出了更高的要求。在使用 EJB 3.0组件技术开发企业应用过程中,它们能够享受到EJB容器提供的线程池、任务调度(@Timeout)服务。现如今,运行于Web容器的Web应用、单独的桌面应用也复杂到需要依赖于线程池、任务调度的这类服务,是时候实现贵族到平民的转变了。
过去,很多企业项目可能会自身实现这类底层的非功能性的服务。从Java SE 5.0开始,线程池服务(即,java.util.concurrent包)已经内置到JDK中。至于任务调度服务,其实,自从Java 2 SDK 1.3以来,Java 2就内置了用于任务调度的定时器(比如,java.util.Timer、javax.swing.Timer)。开源领域的Quartz Scheduler正是能够提供企业级任务调度服务的使能技术,而且EJB 2.x也加强了任务调度的支持。甚至,BEA同IBM合作开发了Timer and Work Manager for Application Servers技术规范(CommonJ),这是专门用来解决Java EE应用中的线程池、任务调度问题的。另外,JMX规范中也定义了javax.management.timer.TimerMBean,开发者借助于它能够实现定时JMX通知。
针对上述各种线程池、任务调度支持,Spring 2.0提供了统一的客户视图、抽象,这使得应用根本不用理会底层的具体实现和机制。本章将从分析Spring 2.0提供的线程池支持入手,并过渡到Spring 2.0对任务调度提供的支持当中,从而进入到下一章内容。
15.1 Spring提供的线程池支持
自从Spring 2.0开始,TaskExecutor接口被引入到Spring平台中,这主要受到Java SE 5.0中java.util.concurrent.Executor的影响。这一接口为各种线程池服务提供了抽象,它在统一客户视图方面起到了最重要的作用。无论是Spring 2.0内部实现中,还是各种基于Spring的企业应用,TaskExecutor的应用随处可见,其定义如下。
public interface TaskExecutor {
//异步或同步执行用户提交的任务
void execute(Runnable task);
}
开发者可以通过execute(Runnable task)方法将待执行的任务提交给TaskExecutor。依据不同的TaskExecutor接口实现,这一任务会以异步或同步的方式进行。如果是同步,则调用者一直处于阻塞状态,直到任务被执行完成。此时,调用者同目标任务的执行处于同一线程中,因此线程上下文信息能够传播到目标任务的执行过程中。如果是异步,则一旦提交完任务,调用者即可返回,并继续进行自身的其他操作。此时,调用者同目标任务的执行位于不同的线程中,因此线程上下文信息很可能不能够在它们之间共享。应用要合理选择同步或异步。比如,在调用execute()期间,如果采用Spring受管事务或Acegi提供的企业级安全性服务,则一旦同步或异步选用不当,事务的ACID属性将得不到保证,而且应用的安全性也得不到保障。
Spring 2.0内置的TaskExecutor接口实现见图15-1,图中除了SyncTaskExecutor外,其他实现都是采用异步方式执行提交的任务的。
图15-1 TaskExecutor继承链
开发者是否还记得,第5章介绍的SimpleApplicationEventMulticaster,它使用了SyncTaskExecutor辅助完成事件的消费工作,其代码摘录如下。
public class SyncTaskExecutor implements TaskExecutor, Serializable {
//同步调用客户提交的任务
public void execute(Runnable task) {
Assert.notNull(task, "Runnable must not be null");
task.run();
}
}
SyncTaskExecutor的使用非常简单,下面给出了示例,摘自Eclipse taskexecutordemo项目。
TaskExecutor te = new SyncTaskExecutor();
te.execute(new LogRunner());
由于SyncTaskExecutor不存在任何属性,因此它的使用最简单。在使用这一实现的过程中,并不会处触发新线程的创建工作,因为提交的任务同调用者同处于一个线程中。相比之下,异步执行用户任务的SimpleAsyncTaskExecutor的使用复杂些,下面给出了示例代码。此时,它会启动新的Thread,并允许开发者控制并发线程的上限(concurrencyLimit),从而起到一定的资源节流作用。默认时,concurrencyLimit取值为–1,即不启用资源节流。
<bean id="simpleAsyncTaskExecutor"
class="org.springframework.core.task.SimpleAsyncTaskExecutor">
<property name="daemon" value="true" />
<property name="concurrencyLimit" value="2" />
<property name="threadNamePrefix" value="simpleAsyncTaskExecutor" />
</bean>
在Spring 2.0内部实现中,JMS集成会使用SimpleAsyncTaskExecutor完成JMS消息监听器的注册、执行等工作,我们将在第16章介绍这方面的内容。每次用户提交新的任务给SimpleAsyncTaskExecutor时,它都会启动新的线程来响应客户请求。这意味着,它并没有提供线程池功能。更何况,在Java EE环境中,随便启动新的线程并不是推荐的做法,因为Java EE容器没有办法管理到这些线程。所以,我们要改进SimpleAsyncTaskExecutor。
Java SE 5.0引入了ThreadPoolExecutor、ScheduledThreadPoolExecutor。Spring 2.0借助于ConcurrentTaskExecutor和ThreadPoolTaskExecutor能够通过IoC配置形式自定义它们暴露的各个属性。比如,下面给出ThreadPoolTaskExecutor的使用示例,其暴露的各个属性其实是ThreadPoolExecutor的属性,这体现了DI容器的优势。
<bean id="threadPoolTaskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="2" />
<property name="keepAliveSeconds" value="200" />
<property name="maxPoolSize" value="10" />
<property name="queueCapacity" value="60" />
</bean>
Spring 2.0在集成java.util.Timer任务调度机制过程中,还引入了TimerTaskExecutor。此时,用户提交的所有任务将交由Timer本身的单个线程执行,其示例配置如下。这一单个线程会以串行的方式完成用户提交给它的所有任务。
<bean id="timerTaskExecutor"
class="org.springframework.scheduling.timer.TimerTaskExecutor">
<property name="delay" value="10000" />
</bean>
在集成Quartz任务调度框架过程中,Spring引入了SimpleThreadPoolTaskExecutor。此时,用户提交的所有任务将交由Quartz维护的线程池执行,其示例配置如下。很显然,开发者能够控制这一线程池的具体细节。在使用Quartz实现任务调度过程中,它会使用内置的线程池处理任务。
<bean id="simpleThreadPoolTaskExecutor"
class="org.springframework.scheduling.quartz.SimpleThreadPoolTaskExecutor">
<property name="makeThreadsDaemons" value="true"/>
<property name="threadCount" value="5" />
<property name="threadNamePrefix" value="simpleThreadPoolTaskExecutor"/>
<property name="waitForJobsToCompleteOnShutdown" value="true" />
</bean>
如果开发者在使用BEA WebLogic 9+和IBM WebSphere 6+版本的Java EE应用服务器,则应用通过JNDI树还能够获得CommonJ提供的Java EE容器受管连接池。我们之前使用的TimerTaskExecutor、SimpleThreadPoolTaskExecutor并没有使用到容器受管连接池,而且它们也不能够使用到Java EE应用的上下文信息,而CommonJ却可以做到。甚至,CommonJ同时支持同步和异步处理用户提交的任务。当然,CommonJ并不是Java EE规范的组成部分,因此只有BEA和IBM客户才能够享受到这一待遇,即WorkManagerTaskExecutor。
WorkManagerTaskExecutor的示例配置如下。我们可以在很多场合使用到这一容器受管的线程池服务,比如,当使用Spring JMS集成开发消息应用时,开发者可以在WebSphere或WebLogic中使用WorkManagerTaskExecutor提供的线程池服务。
<bean id="workManagerTaskExecutor"
class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="jndi/workManager" />
</bean>
分享到:
相关推荐
Spring通过实现ScheduledExecutorService接口的ScheduledExecutorBean,提供了ScheduledTasks的支持。我们可以通过@Scheduled注解来定义一个方法为定时任务,例如每5秒执行一次,或者在特定时间点执行。 当涉及...
总结来说,Spring的线程池支持提供了一种灵活的方式来管理异步任务的执行,通过不同的`TaskExecutor`实现,我们可以根据应用的需要选择合适的策略。同步执行器如`SyncTaskExecutor`适用于简单同步任务,而异步执行器...
总的来说,Spring的线程池支持和任务调度为开发者提供了强大的工具,帮助他们构建可扩展、高性能且易于管理的企业级应用。通过`TaskExecutor`和`ThreadPoolTaskScheduler`,开发者可以在不牺牲灵活性的前提下,确保...
`@Async`注解是Spring提供的一个特性,用于标记方法为异步执行,这样可以避免主线程等待耗时的操作,提高系统效率。本文将详细介绍如何在Spring Boot中创建线程池并配置`@Async`,以及需要注意的一些事项。 首先,...
### Spring3.2.6定时任务...#### 二、Spring线程池配置 Spring框架提供了一个强大的任务调度模块,其中包含了对线程池的支持。下面通过一个具体的示例来展示如何在Spring3.2.6中配置线程池: ```xml <!-- 线程池 --> ...
同时,线程池相关的面试题可能涵盖Spring TaskExecutor,它是Spring提供的异步任务执行框架,支持自定义线程池配置,如核心线程数、最大线程数、队列容量等。 数据库锁是并发控制的重要手段,面试中可能会问到乐观...
标题 "HttpClient + Spring 实现多线程" 涉及到的是如何在Spring框架中使用Apache HttpClient库来创建一个支持多线程的HTTP客户端服务。Apache HttpClient是一个强大的HTTP客户端API,它提供了丰富的功能来处理HTTP...
redis命令实践,基于Spring支持的redis线程池,(redis Cluster,主从Redis,sentenl)。适用人群:计算机,软件工程、人工智能,网络安全,电子信息等专业的大学生课程设计、期末大作业或毕业设计,作为“参考资料...
Spring Data Redis提供了JedisConnectionFactory和LettuceConnectionFactory,它们都支持配置自定义线程池。在Jedis中,我们可以通过`poolConfig`设置线程池的最大连接数、最大空闲连接、超时时间等参数。而在...
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。C3P0的特点包括自动关闭长时间未使用的连接、自动检测并恢复失效的连接、提供连接池的监控等功能。以下是C3P0的基本使用...
Spring框架提供了线程池和定时任务执行的抽象接口:TaskExecutor和TaskScheduler来支持异步执行任务和定时执行任务功能。TaskExecutor是一个抽象接口,定义了execute方法,用来执行Runnable任务。TaskExecutor的实现...
6、新增线程池对spring支持,和spring完美集成;7、包含redis Sentinel Sharded Master Slave线程池;8、包含redis 对象序列化压缩算法,gz和lzma等;9、新增ehcache作为redisx—级缓存;10、支持ehcache多机器共享...
Spring Boot支持Quartz的集成,可以创建、调度和管理任务。通过定义JobDetail和Trigger,我们可以设定任务的执行时间,例如每小时执行一次或者每天特定时间执行。Spring的TaskScheduler或SchedulerFactoryBean也可以...
Spring Boot 使用自定义的线程池执行 Async 任务 本文主要介绍了如何在 Spring Boot 项目中使用自定义的线程池来执行 Async 任务。通过配置自定义的线程池,可以根据项目的需求来调整线程池的参数,从而提高系统的...
"spring-boot-starter-disruptor.zip"正是这样一款启动器,它将Disruptor这一强大的并发工具集成到Spring Boot中,帮助开发者实现高效的线程间通信,避免了线程池的频繁创建,从而优化了系统的性能和开发效率。...
为了解决这个问题,本文提供了一个解决方案:为Spring Session添加一个自定义的线程池。在代码中定义了一个名为springSessionRedisTaskExecutor的Bean,这个线程池会预设核心线程数、最大线程数、线程存活时间、队列...
在 Spring Boot 中使用自定义配置的线程池执行 Async 异步任务,可以通过定义自定义的配置类、创建线程池和开启配置支持来实现。在实际项目中,我们可以根据项目的需求来定制自己的线程池,以提高系统的性能和灵活性...
Spring 提供了强大的事务管理功能,支持编程式和声明式事务管理。声明式事务管理通过在 XML 配置文件或使用 @Transactional 注解来定义事务边界,降低了事务处理的复杂性。编程式事务管理则通过 TransactionTemplate...
在测试方面,Spring4.0提供了更强大的测试支持,包括模拟对象、Web应用程序的集成测试以及对Spring Boot测试的支持,使测试代码更加简洁和高效。 在安全方面,Spring Security 4.0与Spring4.0同步发布,提供了更细...
1. 避免使用自动装配:Spring提供了自动装配功能,通过匹配bean属性或构造函数参数进行依赖注入。尽管能简化配置,但可能会牺牲可读性和可维护性,因此不推荐在大型项目中广泛使用。建议明确地定义bean的依赖关系,...