多线程并发处理起来通常比较麻烦,如果你使用spring容器来管理业务bean,事情就好办了多了。spring封装了java的多线程的实现,你只需要关注于并发事物的流程以及一些并发负载量等特性,具体来说如何使用spring来处理并发事务:
1.了解 TaskExecutor接口
Spring的 TaskExecutor接口等同于java.util.concurrent.Executor接口。 实际上,它存在的主要原因是为了在使用线程池的时候,将对Java 5的依赖抽象出来。 这个接口只有一个方法execute(Runnable task),它根据线程池的语义和配置,来接受一个执行任务。最初创建TaskExecutor是为了在需要时给其他Spring组件提供一个线程池的抽 象。 例如ApplicationEventMulticaster组件、JMS的 AbstractMessageListenerContainer和对Quartz的整合都使用了TaskExecutor抽象来提供线程池。 当然,如果你的bean需要线程池行为,你也可以使用这个抽象层。
2. TaskExecutor接口的实现类
(1)SimpleAsyncTaskExecutor 类
这个实现不重用任何线程,或者说它每次调用都启动一个新线程。但是,它还是支持对并发总数设限,当超过线程并发总数限制时,阻塞新的调用,直到有位置被释放。如果你需要真正的池,请继续往下看。
(2)SyncTaskExecutor类
这个实现不会异步执行。相反,每次调用都在发起调用的线程中执行。它的主要用处是在不需要多线程的时候,比如简单的test case。
(3)ConcurrentTaskExecutor 类
这个实现是对 Java 5 java.util.concurrent.Executor类的包装。有另一个备选, ThreadPoolTaskExecutor类,它暴露了Executor的配置参数作为bean属性。很少需要使用 ConcurrentTaskExecutor, 但是如果ThreadPoolTaskExecutor不敷所需,ConcurrentTaskExecutor是另外一个备选。
(4)SimpleThreadPoolTaskExecutor 类
这个实现实际上是Quartz的SimpleThreadPool类的子类,它会监听Spring的生命周期回调。当你有线程池,需要在Quartz和非Quartz组件中共用时,这是它的典型用处。
(5)ThreadPoolTaskExecutor 类
它不支持任何对 java.util.concurrent包的替换或者下行移植。Doug Lea和Dawid Kurzyniec对java.util.concurrent的实现都采用了不同的包结构,导致它们无法正确运行。 这个实现只能在Java 5环境中使用,但是却是这个环境中最常用的。它暴露的bean properties可以用来配置一个java.util.concurrent.ThreadPoolExecutor,把它包装到一个 TaskExecutor中。如果你需要更加先进的类,比如ScheduledThreadPoolExecutor,我们建议你使用 ConcurrentTaskExecutor来替代。
(6)TimerTaskExecutor类
这个实现使用一个TimerTask作为其背后的实现。它和SyncTaskExecutor的不同在于,方法调用是在一个独立的线程中进行的,虽然在那个线程中是同步的。
(7)WorkManagerTaskExecutor类
这个实现使用了 CommonJ WorkManager作为其底层实现,是在Spring context中配置CommonJ WorkManager应用的最重要的类。和SimpleThreadPoolTaskExecutor类似,这个类实现了WorkManager接口, 因此可以直接作为WorkManager使用。
3.线程池Demo之 ThreadPoolTaskExecutor
(1)编写测试类
01 |
import org.springframework.core.task.TaskExecutor; |
03 |
public class MainExecutor { |
04 |
private TaskExecutor taskExecutor;
|
05 |
public MainExecutor (TaskExecutor taskExecutor) {
|
06 |
this.taskExecutor = taskExecutor;
|
08 |
public void printMessages() {
|
09 |
for(int i = 0; i < 25; i++) {
|
10 |
taskExecutor.execute(new MessagePrinterTask("Message" + i));
|
15 |
private class MessagePrinterTask implements Runnable {
|
16 |
private String message;
|
17 |
public MessagePrinterTask(String message) {
|
18 |
this.message = message;
|
21 |
System.out.println(message);
|
在业务代码中,通常以for循环的方式执行多个事务
for(int k = 0; k < n; k++) {
taskExecutor.execute(new ThreadTransCode());
}
其它繁琐的线程管理的事情就交给执行器去管理。
值得注意的事有两点
1, taskExecutor.execute(new ThreadTransCode()); 激活的线程都是守护线程,主线程结束,守护线程就会放弃执行,这个在业务中式符合逻辑的,在单元测试中为了看到执行效果,需要自行阻塞主线程。
2, taskExecutor.execute(new ThreadTransCode()); 的执行也不是完全安全的,在执行的过程中可能会因为需要的线程查过了线程队列的容量而抛出运行时异常,如有必要需要捕获。
(2)spring的配置
01 |
<? xml version = "1.0" encoding = "UTF-8" ?>
|
02 |
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "/spring-beans.dtd"> |
06 |
< bean id = "threadPool" class = "org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" >
|
08 |
< property name = "corePoolSize" value = "10" />
|
10 |
< property name = "maxPoolSize" value = "50" />
|
12 |
< property name = "queueCapacity" value = "1000" />
|
14 |
< property name = "keepAliveSeconds" value = "300" />
|
16 |
< property name = "rejectedExecutionHandler" >
|
17 |
< bean class = "java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
|
21 |
< bean id = "mainExecutor" class = "supben.MainExecutor" >
|
22 |
< property name = "threadPool" ref = "threadPool" />
|
25 |
< bean id = "springScheduleExecutorTask" class = "org.springframework.scheduling.concurrent.ScheduledExecutorTask" >
|
26 |
< property name = "runnable" ref = "mainExecutor" />
|
28 |
< property name = "delay" value = "10000" />
|
30 |
< property name = "period" value = "5000" />
|
33 |
< bean id = "springScheduledExecutorFactoryBean" class = "org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean" >
|
34 |
< property name = "scheduledExecutorTasks" >
|
36 |
< ref bean = "springScheduleExecutorTask" />
|
(3)调用
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
MainExecutor te = (MainExecutor)appContext.getBean("taskExecutorExample");
te.printMessages();
System.out.println("11111111111111111111111");
(4)效果
相关推荐
这篇博文“Spring基于线程池的定时任务线程异常实践”深入探讨了如何在Spring中结合线程池来执行定时任务,并且特别关注了在实际应用中可能出现的异常情况以及如何处理。 首先,我们需要了解Spring的TaskExecutor...
在这个主题中,我们将深入探讨如何利用Spring MVC与Spring线程池来有效地管理并发请求,并解决数据同步控制问题。 一、Spring MVC与并发处理 1. Spring MVC通过DispatcherServlet接收HTTP请求,然后根据映射规则将...
本实例将深入探讨Spring中的线程池实现,包括其工作原理、配置方式以及如何在实际应用中使用。 首先,我们要理解线程池的基本概念。线程池是由一组预先创建的线程组成的集合,当有新的任务需要执行时,线程池会从池...
在实际应用中,我们需要根据系统的负载和性能需求来调整这些参数,确保线程池的高效运行。 `标签`中的“源码”提示我们可以深入研究Spring线程池的实现,例如分析`ThreadPoolTaskExecutor`的源代码,了解其内部如何...
以下是关于Spring线程池(同步、异步)的详细解析: 一、Spring异步线程池类图 Spring提供了一系列的`TaskExecutor`实现,它们根据不同的需求和场景有不同的特性和行为。这些实现包括但不限于: 1. `...
在Spring Boot应用中,使用线程池和异步处理是提高系统并发性能和响应速度的重要手段。`@Async`注解是Spring提供的一个特性,用于标记方法为异步执行,这样可以避免主线程等待耗时的操作,提高系统效率。本文将详细...
### Spring3.2.6定时任务...#### 二、Spring线程池配置 Spring框架提供了一个强大的任务调度模块,其中包含了对线程池的支持。下面通过一个具体的示例来展示如何在Spring3.2.6中配置线程池: ```xml <!-- 线程池 --> ...
数据库连接是一种关键的有限的昂贵的资源,这一点在多用户网页应用程序中体现的尤为突出。对数据库连接的管理能显著影响到整个应用的伸缩性和健壮性,影响到程序的性能指标。
在Java面试中,Spring框架是不可或缺的知识点,尤其在涉及到线程池的面试题时,对Spring的理解深度往往成为衡量候选人技术能力的重要标准。本文将深入探讨Spring框架的核心原理、重要概念以及与线程池相关的知识。 ...
这个类是Spring对Java内置的`java.util.concurrent.ThreadPoolExecutor`的封装,允许开发者在Spring应用上下文中声明式地定义线程池。在本篇文章中,我们将深入探讨`ThreadPoolTaskExecutor`的配置及其使用,并结合`...
在 Spring Boot 中使用 Java 线程池 ExecutorService 的讲解 Spring Boot 作为一个流行的 Java 框架,提供了许多便捷的功能来帮助开发者快速构建应用程序。其中之一就是使用 Java 线程池 ExecutorService 来管理...
在"Spring线程池demo"中,我们可以看到一个完整的应用实例,它演示了如何在Spring应用中配置和使用线程池。这个项目通常包含以下几个部分: - 配置文件(如`applicationContext.xml`或`application.yml`):包含了`...
总的来说,HttpClient与Spring的结合使得在Java应用中实现高效、安全的多线程HTTP通信变得简单。通过正确配置和管理连接池,可以有效控制并发量,防止资源耗尽,同时利用Spring的容器特性简化代码和提高可维护性。
在实际应用中,`ThreadPoolTaskExecutor`是一个常用的选择,它可以配置线程池的核心线程数、最大线程数、线程存活时间、线程队列大小等参数,以满足不同性能需求。例如,你可以配置一个固定大小的线程池,避免频繁...
在Java数据库连接(JDBC)中,线程池是一种优化数据库操作的重要技术。线程池可以提高应用程序的性能,减少创建和销毁线程的开销,同时管理并发访问数据库的多个请求。本实例中,我们将重点讨论如何使用C3P0这个开源...
《Spring Boot线程池的可观测与易用性提升》 ...开发者可以通过项目地址(https://gitee.com/hanxt/zimug-monitor-threadpool)获取更多详细信息,并将其应用于自己的项目中,提升线程池管理的效率和质量。
在Spring Boot应用中,我们经常需要处理大量的并发请求,这时自定义异步线程池就显得尤为重要。异步处理能够提高应用的响应速度,避免主线程阻塞,从而提升系统性能。本文将详细介绍两种在Spring Boot中实现自定义...
在实际应用中,确保`doJob`方法也是由AOP代理调用,或者使用其他方式获取代理对象,例如通过`ApplicationContext`获取。 此外,使用线程池时要考虑以下几点: 1. **事务边界**:事务的边界应与业务逻辑保持一致。...
然而,在实际应用中,线程池不足的问题经常会出现,导致系统性能下降甚至崩溃。因此,本文将详细介绍Spring Cloud Hystrix线程池不足的解决方法。 Hystrix线程池简介 Hystrix是一个开源的分布式系统解决方案,提供...
其中,异步调用是Spring Boot中的一个重要特性,它允许开发者将一些耗时的任务异步执行,从而提高应用程序的响应速度和性能。在Spring Boot中,可以使用@Async注解来实现异步调用。 使用@Async实现异步调用 在...