iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >spring task和线程池的示例分析
  • 397
分享到

spring task和线程池的示例分析

2023-06-22 06:06:09 397人浏览 八月长安
摘要

小编给大家分享一下spring task和线程池的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!spring task和线程池的研究1、如何实现

小编给大家分享一下spring task和线程池的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

spring task和线程池的研究

1、如何实现spring task定时任务的配置

因工作需要,需要定时执行一个方法,通过相关比较后,发现spring自带的task 可以满足,配置简单

步骤

1)增加配置文件 ,在applicationContext-cfg.xml 主配置文件里面添加 相关task标签

<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)编写bean类和执行方法

编写jobService类,里面实现testjobThread方法,调用的spring注入过的action、service方法

@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()    {        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)配置task相关配置文件,在文件applicationContext-cfg.xml 中增加下列内容

pool-size="5" 该参数主要解决,多个调度并行的问题,如下图5个task任务,建议设置3--5个调度

如果配置参数为 1,下面5个task任务会依次执行,如果一个时间超出,后面的任务一直在等待,影响业务

 <!-- 定时任务 --> <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 * * * ?" />         <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>

使用以上配置后,启动项目就可以定时执行testjobThread方法里面的业务了。

2、task里面的一个job方法如何使用多线程,配置线程池

经过测试,spring task里面的方法是被串行执行的,比如上面配置的方法 testjobThread方法,5秒执行一次,如果有一个执行过程时间过长,后面的一次调度一直等上次执行结束后,才会启动下一次调用。

也就是说spring task是会监控 执行方法的主线程,如果主线程未结束的话,下一次就不会执行。

根据业务需求,这个testjobThread里面的 业务,需要多线程执行 (批量抽取数据)

spring框架里面,推荐使用线程池

1)配置线程池

在applicationContext-cfg.xml文件中增加配置如下

<!-- 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)修改业务操作类为thread类,实现run()方法

添加计数器CountDownLatch ,控制子线程结束后,再结束主线程

注意对象实现@Scope("prototype"),用到了成员变量参数

package cn.hao24.action;import java.util.Date;   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{      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;    }     }

2)修改job调度的方法为多线程,配置3个线程

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));        }    }}

执行效果如下:

虽然 testjobThread 5秒执行一次,但是因为使用到了 latch.await() latch.countDown();需要等子线程执行完毕,才会进行下一次job

子线程每次循环,会sleep 20秒,从下面结果看,3个线程 每隔20秒才打印一次。符合最终要求

线程号:29--taskExecutor-3 --test3:---runing--- 0--20170622145500
线程号:28--taskExecutor-2 --test2:---runing--- 0--20170622145500
线程号:27--taskExecutor-1 --test1:---runing--- 0--20170622145500
线程号:28--taskExecutor-2 --test2:---runing--- 1--20170622145520
线程号:27--taskExecutor-1 --test1:---runing--- 1--20170622145520
线程号:29--taskExecutor-3 --test3:---runing--- 1--20170622145520
线程号:29--taskExecutor-3 --test3:---runing--- 2--20170622145540
线程号:28--taskExecutor-2 --test2:---runing--- 2--20170622145540
线程号:27--taskExecutor-1 --test1:---runing--- 2--20170622145540

spring 线程池配置

默认线程池ThreadPoolTaskExecutor配置

配置核心参数

直接在application.properties中配置核心参数

spring.task.execution.pool.core-size=8spring.task.execution.pool.max-size=12spring.task.execution.pool.keep-alive=60sspring.task.execution.pool.queue-capacity=100000spring.task.execution.pool.allow-core-thread-timeout=truespring.task.execution.thread-name-prefix=swy-task-

创建JavaBean注入

@Configurationpublic class ExecutorConfig {    private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);    @Bean    public Executor asyncServiceExecutor() {        logger.info("start asyncServiceExecutor");        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();        //配置核心线程数        executor.setCorePoolSize(5);        //配置最大线程数        executor.setMaxPoolSize(6);        //配置队列大小        executor.setQueueCapacity(99999);        //配置线程池中的线程的名称前缀        executor.setThreadNamePrefix("swy-task-");        // rejection-policy:当pool已经达到max size的时候,如何处理新任务        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());        //执行初始化        executor.initialize();        return executor;    }}

在配置类,或入口类开启@EnableAsync注解

@SpringBootApplication@EnableAsyncpublic class MultiThreadApplication { public static void main(String[] args) {  SpringApplication.run(MultiThreadApplication.class, args); }}

在Service层或Controller层的类或方法上添加@Async注解

@Asyncpublic void doSomethingAsync(){ logger.info("start executeAsync"); try{  Thread.sleep(5000); }catch(Exception e){  e.printStackTrace(); } logger.info("end executeAsync");}

自定义线程池ThreadPoolTaskExecutor配置

继承ThreadPoolTaskExecutor创建新线程池类

public class CustomThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {    private static final Logger logger = LoggerFactory.getLogger(CustomThreadPoolTaskExecutor.class);    private void showThreadPoolInfo(String prefix){        ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor();        if(null==threadPoolExecutor){            return;        }        logger.info("{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize [{}]",                this.getThreadNamePrefix(),                prefix,                threadPoolExecutor.getTaskCount(),                threadPoolExecutor.getCompletedTaskCount(),                threadPoolExecutor.getActiveCount(),                threadPoolExecutor.getQueue().size());    }    @Override    public void execute(Runnable task) {        showThreadPoolInfo("1. do execute");        super.execute(task);    }    @Override    public void execute(Runnable task, long startTimeout) {        showThreadPoolInfo("2. do execute");        super.execute(task, startTimeout);    }    @Override    public Future<?> submit(Runnable task) {        showThreadPoolInfo("1. do submit");        return super.submit(task);    }    @Override    public <T> Future<T> submit(Callable<T> task) {        showThreadPoolInfo("2. do submit");        return super.submit(task);    }    @Override    public ListenableFuture<?> submitListenable(Runnable task) {        showThreadPoolInfo("1. do submitListenable");        return super.submitListenable(task);    }    @Override    public <T> ListenableFuture<T> submitListenable(Callable<T> task) {        showThreadPoolInfo("2. do submitListenable");        return super.submitListenable(task);    }}

配置新建线程池类的核心参数

@Configurationpublic class ExecutorConfig {    private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);    @Bean    public Executor asyncServiceExecutor() {        logger.info("start asyncServiceExecutor");        ThreadPoolTaskExecutor executor = new CustomThreadPoolTaskExecutor();        //配置核心线程数        executor.setCorePoolSize(5);        //配置最大线程数        executor.setMaxPoolSize(8);        //配置队列大小        executor.setQueueCapacity(99999);        //配置线程池中的线程的名称前缀        executor.setThreadNamePrefix("async-service-");        // rejection-policy:当pool已经达到max size的时候,如何处理新任务        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());        //执行初始化        executor.initialize();        return executor;    }}

在配置类,或入口类开启@EnableAsync注解

@SpringBootApplication@EnableAsyncpublic class MultiThreadApplication { public static void main(String[] args) {  SpringApplication.run(MultiThreadApplication.class, args); }}

在Service层或Controller层的类或方法上添加@Async注解,此时需需注意一定要注明Bean方法名称。

@Async("asyncServiceExecutor")public void doSomethingAsync(){ logger.info("start executeAsync"); try{  Thread.sleep(5000); }catch(Exception e){  e.printStackTrace(); } logger.info("end executeAsync");}

以上是“spring task和线程池的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: spring task和线程池的示例分析

本文链接: https://www.lsjlt.com/news/303073.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • spring task和线程池的示例分析
    小编给大家分享一下spring task和线程池的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!spring task和线程池的研究1、如何实现...
    99+
    2023-06-22
  • Java线程池的示例分析
    小编给大家分享一下Java线程池的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!为什么需要线程池我们知道创建线程的常用方式就是 new Thread() ...
    99+
    2023-06-22
  • Java中线程池的示例分析
    小编给大家分享一下Java中线程池的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Java线程池线程的缺点:线程的创建它会开辟本地方法栈、JVM栈、程序计...
    99+
    2023-06-20
  • Linux系统线程池的示例分析
    Linux系统线程池的示例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。实现原理程序启动之前,创建一定数量的线程,放入空闲的队列中,初始化线程池。这些线程均处于阻塞状态...
    99+
    2023-06-28
  • Python中线程池模块之多线程的示例分析
    这篇文章将为大家详细讲解有关Python中线程池模块之多线程的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1、线程池模块引入from concurrent.futures i...
    99+
    2023-06-15
  • Java并发编程之线程池的示例分析
    这篇文章将为大家详细讲解有关Java并发编程之线程池的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。什么是线程池是一种基于池化思想管理线程的工具。池化技术:池化技术简单点来说,就是提前保存大量的资...
    99+
    2023-06-20
  • Java多线程之线程池七个参数的示例分析
    这篇文章主要介绍Java多线程之线程池七个参数的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!ThreadPoolExecutor是JDK中的线程池实现,这个类实现了一个线程池需要的各个方法,它提供了任务提交...
    99+
    2023-06-14
  • 分析Android中线程和线程池
    目录前言HandlerThreadIntentService线程池的好处ThreadPoolExecutor线程池的分类FixedThreadPoolCachedThreadPool...
    99+
    2024-04-02
  • 客户端JavaScript线程池设计的示例分析
    这篇“客户端JavaScript线程池设计的示例分析”除了程序员外大部分人都不太理解,今天小编为了让大家更加理解“客户端JavaScript线程池设计的示例分析”,给大家总结了以下内容,具有一定借鉴价值,内容详细步骤清晰,细节处理妥当,希望...
    99+
    2023-06-28
  • Node.js中进程和线程的示例分析
    这篇文章给大家分享的是有关Node.js中进程和线程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。进程与线程是一个程序员的必知概念,面试经常被问及,但是一些文章内容只是讲讲理论知识,可能一些小伙伴并没有...
    99+
    2023-06-15
  • java中进程和线程的示例分析
    小编给大家分享一下java中进程和线程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!为什么会有进程在简单的批处理操作系统中,作业时串行执行的,即一个作业...
    99+
    2023-06-20
  • Linux中进程和线程的示例分析
    这篇文章主要为大家展示了“Linux中进程和线程的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux中进程和线程的示例分析”这篇文章吧。计算机实际上可以做的事情实质上非常简单,比如...
    99+
    2023-06-13
  • Spring Boot之@Async异步线程池示例详解
    目录前言一. Spring异步线程池的接口类 :TaskExecutor二、简单使用说明三、定义通用线程池1、定义线程池2、异步方法使用线程池3、通过xml配置定义线程池四、异常处理...
    99+
    2024-04-02
  • Spring的示例分析
    这篇文章将为大家详细讲解有关Spring的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。WHY在诞生之初,创建Spring的主要目的是用来替代更加重量级的企业级Java技术,尤其是EJB。相对于E...
    99+
    2023-05-30
    spring
  • Spring与JDK线程池的简单使用示例详解
    1.配置自定义共享线程池(Spring线程池) @Configuration @EnableAsync public class ThreadPoolConfig{ //主要...
    99+
    2024-04-02
  • java线程编程的示例分析
    这篇文章给大家分享的是有关java线程编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。线程基础◆线程(thread)其实是控制线程(thread of control)的缩写.每一个线程都是独立的,因...
    99+
    2023-06-03
  • Python多线程的示例分析
    这篇文章将为大家详细讲解有关Python多线程的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。线程相对进程来说是“轻量级”的,操作系统用较少的资源创建和管理线程。程序中的线程在相同的内存空间中执行...
    99+
    2023-06-17
  • Java多线程的示例分析
    这篇文章给大家分享的是有关Java多线程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。线程的创建继承Thread实现Runnable实现Callable使用继承Thread类来开发多线程的应用程序在设计...
    99+
    2023-06-20
  • Java中线程的示例分析
    这篇文章主要介绍了Java中线程的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。什么是进程?电脑中时会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互...
    99+
    2023-06-25
  • Spring中IOC和AOP的示例分析
    小编给大家分享一下Spring中IOC和AOP的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Spring是一个开源框架,主要实现两件事,IOC(控制反转...
    99+
    2023-05-30
    spring ioc aop
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作