`

Spring基于线程池的定时任务线挰异常实践

阅读更多

        结论: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定时任务+线程池.docx

    本文将基于Spring3.2.6版本,详细介绍如何配置线程池以及定时任务,并结合具体实例进行解析。 #### 二、Spring线程池配置 Spring框架提供了一个强大的任务调度模块,其中包含了对线程池的支持。下面通过一个具体的...

    spring的自带定时任务

    下面我们将深入探讨Spring的自带定时任务,包括基于注解和XML配置两种方式。 ### 1. Spring定时任务基础 Spring的定时任务功能是通过`org.springframework.scheduling`包中的类来实现的,主要涉及`TaskScheduler`...

    Spring 框架自带定时任务和Quartz定时任务

    Spring Task是在Spring 3.0之后引入的,它使用起来相对简单,支持线程池,可以高效处理不同的定时任务。Spring Task可以通过注解或XML配置文件来配置任务。如果使用注解的方式,仅需要在方法上加上@Scheduled注解,...

    Spring中定时任务

    - `ThreadPoolTaskScheduler`:Spring提供的一个默认实现,基于线程池的任务调度器,可以控制并发执行的定时任务数量。 2. **Quartz Scheduler** - Quartz是一个开源的作业调度框架,可以实现复杂的时间规则和...

    Spring 定时任务源码(spring 三种定时任务的实现方式)

    Spring提供了多种方式来创建和管理定时任务,包括基于接口的TaskExecutor、基于注解的@Scheduled和集成Quartz Scheduler。下面将详细讲解这三种定时任务的实现方式及其源码分析。 1. **基于TaskExecutor的定时任务*...

    spring定时任务执行两次的异常排查处理

    一个tomcat下部署了两个应用,一个是普通web应用syncc,另一个应用syncc_wx属于微信公众号后台程序涉及消息定时推送,tomcat未分离...”spring定时任务执行两次的异常排查处理.docx"针对上述描述问题进行分析和解决。

    Spring定时任务实现(非Web项目)

    综上所述,Spring提供的定时任务功能使得开发者能够轻松地在非Web项目中实现复杂的时间驱动逻辑,无论是简单的定时执行还是基于Cron表达式的复杂调度,Spring都能提供强大的支持。通过合理配置和编程,我们可以创建...

    spring 线程池实例

    在Java编程中,Spring框架提供了一种优雅的方式来管理和执行异步任务,这就是Spring的线程池。线程池是多线程编程中的一个重要概念,它能够有效地管理并发任务的执行,提高系统的性能和效率。本实例将深入探讨Spring...

    springmvc+spring线程池处理http并发请求数据同步控制问题

    1. Spring提供了一个名为ThreadPoolTaskExecutor的实现,它基于Java的ExecutorService接口,允许我们自定义线程池配置,如核心线程数、最大线程数、队列容量、超时时间等。 2. 通过在配置文件中声明一个...

    Spring3.0定时任务简单实例web工程

    在本实例中,我们关注的是Spring 3.0版本中的定时任务功能,这是一个基于Web工程的简单示例,适合在MyEclipse环境中运行。 首先,我们要了解Spring 3.0中的定时任务是如何工作的。Spring提供了`TaskExecutor`接口和...

    spring定时任务关键jar包(齐全)

    其中,Spring的定时任务功能是许多项目中的重要组成部分,它允许开发者安排和执行周期性的任务。本文将详细探讨Spring定时任务的关键知识点,并与提供的jar包列表关联。 首先,Spring定时任务主要依赖于`spring-...

    spring动态分配定时任务

    2.通过Spring是JAR-quartz写的一个定时任务 1)普通的定时任务,定时完成指定的任务 2)通过前台动态分配定时任务 可指定多个任务,可同时执行任务,可以精确到时分秒扫描并执行任务 3)可以完成稍微复杂点的任务 ...

    基于Spring中的线程池和定时任务功能解析

    基于Spring中的线程池和定时任务功能解析 Spring框架提供了线程池和定时任务执行的抽象接口:TaskExecutor和TaskScheduler来支持异步执行任务和定时执行任务功能。TaskExecutor是一个抽象接口,定义了execute方法,...

    spring xml 定时任务

    在Spring框架中,XML配置是传统且广泛使用的方式来设置应用的组件和行为,包括实现定时任务。定时任务在软件开发中扮演着重要角色,它允许应用程序在预设的时间执行特定的任务,例如数据清理、日志归档或者发送通知...

    springboot定时任务的动态开启关闭

    在Spring Boot应用中,定时任务是一项非常实用的功能,它允许我们按照预定的时间间隔执行特定的任务。Spring Boot提供了Spring Scheduler抽象来实现这样的需求,使得开发者能够方便地管理和控制定时任务。本篇文章将...

    Springboot 通过ThreadPoolTaskScheduler实现定时任务.rar

    本项目采用`ThreadPoolTaskScheduler`来实现定时任务,这是一种基于Java线程池的定时任务调度器,相比Spring的`@Scheduled`注解,它提供了更灵活的配置和管理方式。 1. **ThreadPoolTaskScheduler介绍** `...

    spring动态配置定时任务

    在Java Spring框架中,动态配置定时任务是一项非常实用的功能,它允许我们根据需求灵活地更改或添加定时任务,而无需每次改动都重启应用。本文将深入探讨如何在Spring中实现这种动态配置,以及如何结合数据库来管理...

    Spring定时任务(Web项目)

    它提供了基于`@Scheduled`注解和`TaskScheduler`接口的两种定时任务实现方式。`@Scheduled`适用于简单的定时任务,而`TaskScheduler`则更灵活,可以用于复杂的调度需求。 二、@Scheduled注解使用 1. 配置启用定时...

Global site tag (gtag.js) - Google Analytics