Spring task and thread pool research

Original address: http://blog.csdn.net/qihezhuanjia123/article/details/73604955

involves the following

1. How to implement the configuration of spring task timing tasks

2. How a job method in a task uses multithreading and configures the thread pool

如何配置等待子线程结束后,再结束主线程

1. How to implement the configuration of spring task timing tasks

Due to work needs, a method needs to be executed regularly. After related comparisons, it is found that the task that comes with spring can be satisfied, and the configuration is simple

step

1) Add a configuration file and add the relevant task tag in the applicationContext-cfg.xml main configuration file

[html] view plain copy

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:task="http://www.springframework.org/schema/task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    
       http://www.springframework.org/schema/tx   
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd    
       http://www.springframework.org/schema/aop   
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd    
       http://www.springframework.org/schema/context   
       http://www.springframework.org/schema/context/spring-context-3.0.xsd  
       http://www.springframework.org/schema/task  
       http://www.springframework.org/schema/task/spring-task-3.0.xsd  
       http://www.springframework.org/schema/jee       
       http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">  

2) Write bean class and execute method

Write the jobService class, which implements the testjobThread method, and invokes the spring-injected action and service methods

[java] view plain copy

@Component("jobService")  
public class jobService  
{  
    private static Logger logger = Logger.getLogger(jobService.class);  

    @Autowired  
    private ThreadPoolTaskExecutor taskExecutor;  
    final CountDownLatch countDownLatch = new CountDownLatch(3);   

    /**  
    * @Title: DZFP_job  
    * @Description:开票定时任务 
    */  
    public void testjobThread()  
    {  
        Date startdate = new Date();  
        logger.info("DZFP_job_JOB 开始执行任务...,时间   " + startdate);  
        try  
        {  
            DzfpAction.Dzfp_SendAll();  
        }  
        catch (Exception e)  
        {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
            logger.error(StringUtil.grabExceptionMessage(e));  
        }  
        Date enddate = new Date();  
        logger.info("DZFP_job_JOB 任务完成...时间  " + enddate + "   耗时   " + String.valueOf(enddate.getTime() - startdate.getTime()) + "毫秒");  
    }  

3) Configure task-related configuration files, and add the following content to the file applicationContext-cfg.xml

pool-size=”5” This parameter mainly solves the problem of multiple scheduling in parallel, as shown in the figure below for 5 tasks, it is recommended to set 3–5 scheduling

If the configuration parameter is 1, the following five tasks will be executed in sequence. If one of the tasks exceeds the time, the following tasks will be waiting, affecting the business.

[html] view plain copy

<!-- 定时任务 -->  
<task:scheduler id="scheduler" pool-size="5" />  
<task:scheduled-tasks scheduler="scheduler">  
    <!-- 每天7点到7点55, 每隔5分钟执行一次 "0 0/5 7 * * ?"-->  
    <task:scheduled ref="jobService" method="DZFPgetInvoie_job" cron="0 0/30 * * * ?" />  
    <task:scheduled ref="jobService" method="DZFPgetInvoie_hong_job" cron="0 0/30 * * * ?" />  
       <span style="white-space:pre">   </span><task:scheduled ref="jobService" method="testjobThread" cron="0/5 * * * * ?" />  
    <task:scheduled ref="jobService" method="hzgd_job" cron="0/30 * * * * ?" />  
    <task:scheduled ref="jobService" method="alipay_pay_job" cron="0/30 * * * * ?" />  
</task:scheduled-tasks>  

After using the above configuration, the startup project can execute the business in the testjobThread method regularly.

2. How a job method in a task uses multithreading and configures the thread pool

After testing, the methods in the spring task are executed serially. For example, the method testjobThread method configured above is executed every 5 seconds. If there is one execution process that takes too long, the subsequent scheduling will wait until the last execution ends. will start the next call.

That is to say, the spring task is the main thread that monitors the execution method. If the main thread does not end, it will not be executed next time.

According to business requirements, the business in this testjobThread requires multi-threaded execution (batch extraction of data)

In spring framework, it is recommended to use thread pool

1) Configure the thread pool and add the following configuration in the applicationContext-cfg.xml file

[html] view plain copy

<!-- spring线程池-->             
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">  
    <!-- 线程池维护线程的最少数量 -->  
    <property name="corePoolSize" value="5" />  
    <!-- 线程池维护线程所允许的空闲时间,默认为60s  -->  
    <property name="keepAliveSeconds" value="200" />  
    <!-- 线程池维护线程的最大数量 -->  
    <property name="maxPoolSize" value="20" />  
    <!-- 缓存队列最大长度 -->  
    <property name="queueCapacity" value="20" />  
    <!-- 对拒绝task的处理策略   线程池对拒绝任务(无线程可用)的处理策略,目前只支持AbortPolicy、CallerRunsPolicy;默认为后者-->  
    <property name="rejectedExecutionHandler">  
    <!-- AbortPolicy:直接抛出java.util.concurrent.RejectedExecutionException异常 -->  
        <!-- CallerRunsPolicy:主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度 -->  
        <!-- DiscardOldestPolicy:抛弃旧的任务、暂不支持;会导致被丢弃的任务无法再次被执行 -->  
        <!-- DiscardPolicy:抛弃当前任务、暂不支持;会导致被丢弃的任务无法再次被执行 -->  
        <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />  
    </property>  
    <property name="waitForTasksToCompleteOnShutdown" value="true" />  
</bean>  

2) Modify the business operation class to thread class and implement the run() method

Add a counter CountDownLatch, after the control child thread ends, end the main thread

Note that the object implements @Scope("prototype"), which uses member variable parameters

[java] view plain copy

package cn.hao24.action;  
import java.util.Date;  
<name code="" class="java">import java.util.concurrent.CountDownLatch;  

import org.springframework.context.annotation.Scope;  
import org.springframework.stereotype.Component;  

import cn.hao24.util.DateUtil;  
import cn.hao24.util.SpringContextUtils;  

@Component("testThreadAction")  
@Scope("prototype")  
public class testThreadAction extends Thread  
{  

/** 
 * spring tash默认是单线程 串行执行,即一个方法执行完成前,后面的job不会执行的 
 * 但是如果主方法里面产生了thread线程, 主线程如果不等子线程结束后 就结束的话, task任务会产生多次调度 
 */  

    private String Treadname;  
    private CountDownLatch latch;  

    public testThreadAction(String Treadname,CountDownLatch latch){  
        this.Treadname=Treadname;  
        this.latch=latch;  
    }  

    @Override  
    public void run()  
    {  


        try  
        {  
            //主业务方法  
            for (int i = 0; i < 10; i++)  
            {  
                Thread current = Thread.currentThread();  
                System.out.println("线程号:"+current.getId() +"--"+current.getName()+" --"+Treadname +":---runing--- "+i+"--"+DateUtil.format(new Date(), "yyyyMMddHHmmss") );  
                Thread.sleep(20000);  
            }  
        }  
        catch (InterruptedException e)  
        {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }finally{  
            //设置实例 执行完毕  
            latch.countDown();  
        }  

    }  
    public void setTreadname(String treadname)  
    {  
        Treadname = treadname;  
    }  


    public void setLatch(CountDownLatch latch)  
    {  
        this.latch = latch;  
    }  


}</name>  

2) The method of modifying job scheduling is multi-threading and configuring 3 threads
[java] view plain copy

package cn.hao24.job;  

import java.util.Date;  
import java.util.concurrent.CountDownLatch;  

import javax.annotation.Resource;  

import org.apache.log4j.Logger;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;  
import org.springframework.stereotype.Component;  

import cn.hao24.action.DzfpAction;  
import cn.hao24.action.HzgdAction;  
import cn.hao24.action.KJGOrderjob;  
import cn.hao24.action.testThreadAction;  
import cn.hao24.service.ZFBService;  
import cn.hao24.util.SpringContextUtils;  
import cn.hao24.util.StringUtil;  

@Component("jobService")  
public class jobService  
{  
    private static Logger logger = Logger.getLogger(jobService.class);  

    @Autowired  
    private ThreadPoolTaskExecutor taskExecutor;  
    final CountDownLatch countDownLatch = new CountDownLatch(3);   
    public void testjobThread()  
    {  
        try  
        {  
            CountDownLatch latch=new CountDownLatch(3);  //java工具类,类似与计数器,主要实现子线程未结束钱,主线程一直等待  
            testThreadAction test1 = (testThreadAction)SpringContextUtils.getBean("testThreadAction","test1",latch);  
            testThreadAction test2 = (testThreadAction)SpringContextUtils.getBean("testThreadAction","test2",latch);  
            testThreadAction test3 = (testThreadAction)SpringContextUtils.getBean("testThreadAction","test3",latch);  
            taskExecutor.execute(test1);  
            taskExecutor.execute(test2);  
            taskExecutor.execute(test3);  
            latch.await(); //子线程未结束前,一直等待  
            //test1.run();  
        }  
        catch (Exception e)  
        {  
            e.printStackTrace();  
            logger.error(StringUtil.grabExceptionMessage(e));  
        }  
    }  
}  

The execution effect is as follows:

Although the testjobThread is executed once every 5 seconds, because latch.await() latch.countDown() is used; the next job will not be performed until the child thread is executed.

Each time the child thread loops, it will sleep for 20 seconds. From the results below, the three threads only print every 20 seconds. meet final requirements

Thread number: 29–taskExecutor-3 –test3:—runing— 0–20170622145500
Thread number: 28–taskExecutor-2 –test2:—runing— 0–20170622145500
Thread number: 27–taskExecutor-1 –test1:—runing— 0– 20170622145500
Thread ID: 28–taskExecutor-2 –test2:—runing– 1–20170622145520
Thread ID: 27–taskExecutor-1 –test1:–runing– 1–20170622145520
Thread ID: 29–taskExecutor-3 –test3:–runing– 1 –20170622145520Thread
number: 29–taskExecutor-3 –test3:—runing— 2–20170622145540Thread
number: 28–taskExecutor-2 –test2:—runing— 2–20170622145540Thread
number: 27–taskExecutor-1 –test1:—runing— 2–20170622145540

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325899104&siteId=291194637