结论:Spring基于线程池的定时任务,线挰异常或内存溢出导致线程挂了,还会新启线程继续工作。
实例重现:
springMVC.properties
#the thread pool config thread.corePoolSize=3 thread.maxPoolSize=8 thread.keepAliveSeconds=6 thread.queueCapacity=2 timing.query.status.interval=3000
springMVC-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd "> <context:component-scan base-package="com.bijian.study"></context:component-scan> <!-- 系统配置文件 --> <context:property-placeholder location="classpath:springMVC.properties" /> <mvc:annotation-driven></mvc:annotation-driven> <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 核心线程数,默认为1 --> <property name="corePoolSize" value="${thread.corePoolSize}" /> <!-- 最大线程数,默认为Integer.MAX_VALUE --> <property name="maxPoolSize" value="${thread.maxPoolSize}" /> <!-- 队列最大长度,一般需要设置值>=notifyScheduledMainExecutor.maxNum;默认为Integer.MAX_VALUE --> <property name="queueCapacity" value="${thread.queueCapacity}" /> <!-- 线程池维护线程所允许的空闲时间,默认为60s --> <property name="keepAliveSeconds" value="${thread.keepAliveSeconds}" /> <!-- 线程池对拒绝任务(无线程可用)的处理策略,目前只支持AbortPolicy、CallerRunsPolicy;默认为后者 --> <property name="rejectedExecutionHandler"> <!-- AbortPolicy:直接抛出java.util.concurrent.RejectedExecutionException异常 --> <!-- CallerRunsPolicy:主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度 --> <!-- DiscardOldestPolicy:抛弃旧的任务、暂不支持;会导致被丢弃的任务无法再次被执行 --> <!-- DiscardPolicy:抛弃当前任务、暂不支持;会导致被丢弃的任务无法再次被执行 --> <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" /> </property> </bean> <task:scheduled-tasks> <!-- <task:scheduled ref="com.bijian.study.scheduled.TestScheduled" method="execute" cron="0 43 22 * * ?" /> --> <task:scheduled ref="com.bijian.study.scheduled.TestScheduled" method="execute" fixed-delay="${timing.query.status.interval}" /> </task:scheduled-tasks> <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/views" /> <property name="suffix" value=".jsp" /> </bean> </beans>
ScheduledService.java
package com.bijian.study.service; public interface ScheduledService { void noNormalTest(); void normalTest(); }
ScheduledServiceImpl.java
package com.bijian.study.service.impl; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.bijian.study.entity.Person; import com.bijian.study.service.ScheduledService; import com.bijian.study.util.JsonUtil; @Service("scheduledService") public class ScheduledServiceImpl implements ScheduledService { private static Logger logger = LoggerFactory.getLogger(HelloServiceImpl.class); private static int COUNT = 0; @Override public void noNormalTest() { logger.info("entry ScheduledService noNormalTest:{}" ,"entry"); try { Thread.sleep(10000); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { int j = 200/0; List<Person> personList = new ArrayList<Person>(3); personList.add(new Person("bijian", 10)); personList.add(new Person("lisi", 20)); personList.add(new Person("zhangshan", 30)); List<Person> personList2 = new ArrayList<Person>(); int i = 0; int count = personList.size(); while(i < count) { personList2.add(personList.get(i)); if(i == 2) { personList2.clear(); } } }catch(Exception e) { logger.error("noNormalTest Exception:{}", e); } logger.info("entry ScheduledService noNormalTest:{}" ,"exit"); } @Override public void normalTest() { logger.info("entry ScheduledService normalTest:{}" ,"entry"); // try { // //Thread.sleep(10000); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } if(COUNT++ == 0) { List<Person> personList = new ArrayList<Person>(); for(int i=0;i<1000000;i++) { personList.add(new Person("bijian", 10)); personList.add(new Person("lisi", 20)); personList.add(new Person("zhangshan", 30)); } logger.info("personList:{}", JsonUtil.toFullJson(personList)); } } }
BaseScheduled.java
package com.bijian.study.scheduled; public interface BaseScheduled { void execute(); }
TestScheduled.java
package com.bijian.study.scheduled; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import com.bijian.study.controller.HelloController; import com.bijian.study.service.ScheduledService; @Service(value = "com.bijian.study.scheduled.TestScheduled") public class TestScheduled implements BaseScheduled { private static Logger logger = LoggerFactory.getLogger(HelloController.class); @Autowired @Qualifier("taskExecutor") private ThreadPoolTaskExecutor threadPoolTaskExecutor; @Autowired private ScheduledService scheduledService; private static int COUNT = 0; @Override public void execute() { logger.info("enter TestScheduled"); if(0 == COUNT) { threadPoolTaskExecutor.execute(new Runnable() { @Override public void run() { try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } scheduledService.noNormalTest(); } }); }else { // class MyThread implements Runnable { // // private String name; // // public MyThread(String name) { // this.name = name; // } // // @Override // public void run() { //// try { // logger.info("MyThread name:{}", name); // try { // Thread.sleep(30000); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // scheduledService.normalTest(); //// }catch(Throwable e) { //// logger.info("exception:{}", e); //// } // } // } threadPoolTaskExecutor.execute(new Runnable() { @Override public void run() { scheduledService.normalTest(); } }); } COUNT ++; logger.info("exit TestScheduled"); } }
完整工程代码见附件《SpringMVC.zip》。
相关推荐
Spring3.2.6定时任务+线程池,实现系统后台任务多线程处理
Spring 框架自带定时任务使用 stask.xml Quartz定时任务
spring的自带定时任务 基于注解和xml配置
2.通过Spring是JAR-quartz写的一个定时任务 1)普通的定时任务,定时完成指定的任务 2)通过前台动态分配定时任务 可指定多个任务,可同时执行任务,可以精确到时分秒扫描并执行任务 3)可以完成稍微复杂点的任务 ...
Spring3.x企业应用开发实战 中 Spring 定时任务源码(spring 三种定时任务的实现方式),Spring quartz java 定时器 定时任务 源码
spring整合quartz定时任务调度..........
Spring定时任务的几种实现,欢迎交流!
一个tomcat下部署了两个应用,一个是普通web应用syncc,另一个应用syncc_wx属于微信公众号后台程序涉及消息定时推送,tomcat未分离...”spring定时任务执行两次的异常排查处理.docx"针对上述描述问题进行分析和解决。
springmvc+spring线程池处理http并发请求数据同步控制问题
完整的javaspring定时任务的实现,通过配置数据库可以实现定时任务的修改,不必频繁的修改配置文件,大家可以自行在上面实现更多的定时任务管理。数据库表结构已经上传
下面小编就为大家带来一篇基于Spring中的线程池和定时任务功能解析。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
基于Spring的Quartz动态定时任务增删改查,代码简洁。后端采用SpringMvc+Spring+Mybatis+Quartz,前端采用Bootstrap框架,数据库采用MySQL;完成定时任务动态任务初始化,增删改查
通过配置文件来实现定时任务
Spring + quartz 定时任务修改定时时间不重启服务
使用mybatis读写mysql数据库, spring实现定时任务, 按照间隔时间或固定时间方式执行定时任务
文档讲述了SpringTask动态定时任务的使用以及配置方法。可拔插的使用在相关的项目中去
本案例实现利用Spring技术实现定时任务功能,用于Web项目
spring自带定时任务程序,其中包括定时任务配置的xml文件、定时任务测试类和定时任务说明文档,仅供大家参考使用。
spring-boot 2.1.6 定时任务集群、定时任务持久化到mysql数据库。