spring的Scheduled(定时任务)和多线程
一、前言
在我们日常的开发中,经常用到数据同步的更新,这时我们采用的是spring的定时任务和java的多线程进行数据的更新,进行时实的服务调用。
二.实现思路
1.创建线程类
2.创建ExecutorService线程连接池
3.调用线程池操作
4.spring的Scheduled(定时任务)配置
三.创建线程类
创建的线程类,我们采用的是实现Runnable接口,使用该类可以共享,在线程中要么继承Thread,或者实现Runnable接口,其中Thread是实现了Runnable的接口,实现Runnable接口可以更好的扩展和共享类,因为java是单继承多实现的程序。
public class ArchiveTask implements Runnable {
/**
* log.
*/
private static Logger logger = LoggerFactory.getLogger(ArchiveTask.class);
//注:由于spring事务配置采用的注解的方式来配置传播性配置,此类没有在spring传播配置里面,所以不能用自动装配的方式来配置
private static FaxRecvArchiveCtrl faxRecvArchiveCtrl = AppContextAware.getBean(FaxRecvArchiveCtrl.class);
private FaxRecvArchiveDTO faxRecvArchiveDTO;
/**
* CountDownLatch是一个同步辅助类,在一组线程在执行操作之前,允许一个或多线程处于等待
* 主要方法
* public CountDownLatch(int count);
* public void countDown();
* public void await() throws InterruptedException
*
* 构造方法参数指定了计数的次数
* countDown方法,当前线程调用此方法,则计数减一
* awaint方法,调用此方法会一直阻塞当前线程,直到计时器的值为0
*
*/
private CountDownLatch latch;
public ArchiveTask(FaxRecvArchiveDTO faxRecvArchiveDTO, CountDownLatch latch) {
this.faxRecvArchiveDTO = faxRecvArchiveDTO;
this.latch = latch;
}
@Override
public void run() {
try {
faxRecvArchiveCtrl.updateArchiveFileFlag(ServiceFactory.getCurrentSessionId(), faxRecvArchiveDTO);
} catch (Exception ex) {
logger.debug("["+this.faxRecvArchiveDTO.getFaxKey()+"]线程执行异常,错误信息为:"+ex.getMessage());
} finally{
logger.debug("线程执行完:"+this.faxRecvArchiveDTO.getFaxKey());
latch.countDown();
}
}
}
四、调用线程池操作
public class EasyFaxArchiveFileMgr {
/**
* 日志
*/
Logger logger = LoggerFactory.getLogger(EasyFaxArchiveFileMgr.class);
/**
* 线程池数量
*/
private int ThreadNum = 5;
private static FaxRecvArchiveCtrl faxRecvArchiveCtrl = AppContextAware.getBean(FaxRecvArchiveCtrl.class);
private static List<FaxRecvArchiveDTO> noArchiveList = new ArrayList<FaxRecvArchiveDTO>();
public void archiveFile() throws ShineException{
noArchiveList = faxRecvArchiveCtrl.getFaxRecvNoArchiveFile();
ExecutorService executorService = Executors.newFixedThreadPool(ThreadNum);
List<ArchiveTask> taskList = new ArrayList<ArchiveTask>();
synchronized (noArchiveList) {
while(CollectionUtils.isEmpty(noArchiveList) == false) {
try {
//定义计数器
int countLatch = (noArchiveList.size() > ThreadNum) ? ThreadNum :noArchiveList.size();
CountDownLatch latch = new CountDownLatch(countLatch);
//组织任务
for(int i = 0; i < ThreadNum; i++){
if(CollectionUtils.isEmpty(noArchiveList) == false) {
taskList.add(new ArchiveTask(noArchiveList.remove(0),latch));
}else{
break;
}
}
//提交任务
if (CollectionUtils.isEmpty(taskList) == false) {
for (int i = 0, size = taskList.size(); i < size; i++) {
executorService.submit(taskList.get(i));
}
}//等待所有线程都执行完
latch.await();
} catch(Exception ex) {
logger.error("线程池处理出错,原因:"+ex.getMessage());
} finally {
taskList.clear();
}
//关闭线程连接池
executorService.shutdown();
}
}
}
}
五.spring配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="archiveFileScheduler"/>
</list>
</property>
</bean>
<bean id="archiveFileScheduler" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="delay">
<!-- 启动30秒后开始运行 -->
<value>30000</value>
</property>
<property name="period">
<!-- 每10秒运行 -->
<value>10000</value>
</property>
<property name="timerTask">
<ref bean="archiveFileHandleMethodInvoker" />
</property>
</bean> <bean id="archiveFileHandleMethodInvoker" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
<property name="targetObject">
<ref bean="com.shine.emofs.thirdparty.easyfax.ctrl.EasyFaxArchiveFileMgr" />
</property>
<property name="targetMethod">
<value>archiveFile</value>
</property>
</bean>
</beans>
六、参考:
ExecutorService线程连接池:http://www.itzhai.com/the-executorservice-common-method-newfixedthreadpool-of-create-fixed-size-thread-pool.html#read-more
spring的Scheduled(定时任务)和多线程的更多相关文章
- Spring Boot Scheduled定时任务特性
SpringBoot中的Scheduled定时任务是Spring Boot中非常常用的特性,用来执行一些比如日切或者日终对账这种定时任务 下面说说使用时要注意的Scheduled的几个特性 Sched ...
- spring的@Scheduled定时任务,同一时间段的定时任务只会执行一个,其余的会被阻塞,@Scheduled注解定时任务并发执行解决办法,即多线程运行定时任务
原文:https://blog.csdn.net/qq_35937303/article/details/88851064 现有两个定时任务 @Component("aa") pu ...
- Spring注解@Scheduled定时任务
一.首先配置applicationContext-task.xml (1)添加 xmlns:task="http://www.springframework.org/schema/task& ...
- spring注解scheduled实现定时任务
只想说,spring注解scheduled实现定时任务使用真的非常简单. 一.配置spring.xml文件 1.在beans加入xmlns:task="http://www.springfr ...
- Spring 的@Scheduled注解实现定时任务运行和调度
Spring 的@Scheduled注解实现定时任务运行和调度 首先要配置我们的spring.xml --- 即spring的主配置文件(有的项目中叫做applicationContext.xm ...
- Spring @Scheduled定时任务动态修改cron参数
在定时任务类上增加@EnableScheduling注解,并实现SchedulingConfigurer接口.(注意低版本无效) 设置一个静态变量cron,用于存放任务执行周期参数. 另辟一线程,用于 ...
- Spring的@Scheduled任务调度
一. 定时任务实现方式 定时任务实现方式: Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行 ...
- Spring Boot (29) 定时任务
使用场景:数据定时增量同步,定时发送邮件,爬虫定时抓取 定时任务概述 定时任务:顾名思义就是在特定/指 定的时间进行工作,比如我们的手机闹钟,他就是一种定时的任务. 实现方式: 1.Timer:JDK ...
- Spring Boot 实现定时任务的 4 种方式
作者:Wan QingHua wanqhblog.top/2018/02/01/SpringBootTaskSchedule/ 定时任务实现的几种方式: Timer:这是java自带的java.uti ...
随机推荐
- 初学Java 精简知识点总结
面对Java丰富的知识资料,很多初学者难免觉得迷惘,该学什么,怎么去学?下面给大家讲Java基础知识做了精简总结,来帮助你梳理学习思路,赶快看看吧! 方法/步骤1 对象的初始化(1) 非静态对象的初始 ...
- servlet 上传文件 参数中文乱码
获取数据时需要进行转码 item.getString("网站使用编码utf-8,GBK等");
- 英文写作——冠词的使用(Use 0f Articles)
1.使用'a','an','the'和不使用冠词的基本规则: <1>泛指,不可数名词不能有任何冠词 <2>泛指,可数,复数名词前不能有冠词 <3>泛指,可数,单数名 ...
- C语言基础(8)-const,volatile,register关键字
1 const const是定义一个常量 2 volatile 代表定义一个变量,这个变量值可能在CPU指令之外被改变 volatile int a;//定义了一个volatile类型的int变量 通 ...
- [Nhibernate]二级缓存(一)
目录 写在前面 文档与系列文章 二级缓存 Nhibernate二级缓存提供程序 一个例子 总结 写在前面 上篇文章介绍了nhibernate中一级缓存的相关内容,一级缓存过期时间和ISession对象 ...
- Android高手速成--第三部分 优秀项目
主要介绍那些Android还不错的完整项目,目前包含的项目主要依据是项目有意思或项目分层规范比较好.Linux项目地址:https://github.com/torvalds/linuxAndroid ...
- setTimeout和setInterval的注意事项
精准问题 setTimeout的问题在于它并不是精准的,例如使用setTimeout设定一个任务在10ms后执行,但是在9ms后,有一个任务占用了5ms的cpu时间片,再次轮到定时器执行时,时间已经过 ...
- runtime的黑魔法
要说明runtime,首先要明白objc这门语言,是基于C的封装.真是因为runtime,objc才有了面对对象的特性. 也就说,所有objc的语言,在运行时都会转换成C. 也是基于这样的特性,run ...
- MySQL分库分表的一些技巧
分表是分散数据库压力的好方法. 分表,最直白的意思,就是将一个表结构分为多个表,然后,可以再同一个库里,也可以放到不同的库. 当然,首先要知道什么情况下,才需要分表.个人觉得单表记录条数达到百万到千万 ...
- MySQL学习笔记(2/2)
SQL种类 DDL/DML/DQL/DCL 中括号[]里面的表示可选,大括号{}里面的表示必须从里面选一个,FEILED表示字段. 数据定义语言(DDL):CREATE.DROP.ALTER 用于定义 ...