启动一个异步线程去执行一个任务
2018-01-19 21:54
453 查看
1.业务场景: 浦发银行充值接口,他行卡充值不是实时将充值结果返回的,需要我们自己去手动去查。银行充值接口实现业务都是预计2小时到账,但如果需求修改发送充值接口后,立马去调用银行提供的状态查询接口,将状态查询回来时,需要启动一个异步线程将结果查询回来.
代码编辑如下: <?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd" default-autowire="byName" default-lazy-init="false"> <!-- 使用spring提供的线程池 --> <bean id="executePool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 线程池维护线程的最小数量 --> <property name="corePoolSize" value="1"></property> <!-- 线程池维护线程所允许的空闲时间 --> <property name="maxPoolSize" value="5"></property> <!-- 线程池所使用的最大数量 --> <property name="keepAliveSeconds" value="30000" /> <!-- 线程池所使用的缓冲队列 --> <property name="queueCapacity" value="1000" /> </bean> <bean id="asyExecuteService" class="com.adai.asy.service.imp.AsyExecuteServiceImp" destroy-method="destory"> <property name="executePool" ref="executePool" /> </bean> <context:annotation-config/> <context:component-scan base-package="com.adai"/> </beans>
package com.adai.asy.service; import java.util.Map; /** * 异步服务接口 * @author v-chenk25 * @since 2018-01-19 21:35 * */ public interface AsyExecuteService { /** * 异步服务 * @param taskId 服务id * @param sendMap 请求参数 */ public void execute(String taskId , Map<String,Object> sendMap); }
package com.adai.asy.service; import java.util.Map; /** * 异步接口 * @author v-chenk25 * @since 2018-01-19 21:35 * */ public interface AsyService { /** * 异步交易接口 * @param sendMap 请求参数 */ public void execute(Map<String,Object> sendMap) ; }
package com.adai.asy.service.imp; import java.util.Date; import java.util.Map; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import com.adai.asy.service.AsyExecuteService; import com.adai.asy.service.AsyService; import com.adai.constant.Dict; import com.adai.util.Utils; /** * 异步服务实现类:这里需要注入线程池启动一个线程去执行任务 * @author v-chenk25 * @since 2018-01-19 21:35 */ public class AsyExecuteServiceImp implements AsyExecuteService , ApplicationContextAware{ private ApplicationContext context ; private ThreadPoolTaskExecutor executePool ; public void execute(String taskId, final Map<String, Object> sendMap) { sendMap.put(Dict.TASKID, taskId) ; final AsyService asyService = (AsyService) this.context.getBean(taskId) ; this.executePool.execute(new Runnable() { public void run() { asyService.execute(sendMap); } }); } public Map<String,Object> prepareReq(Map<String,Object> sendMap){ sendMap.put(Dict.ORDERID, Utils.getCurrentFormat(new Date(), Dict.YNRH)) ; return sendMap; } public void destory() { if(this.executePool != null) { this.executePool.shutdown(); } } public void setApplicationContext(ApplicationContext context) throws BeansException { this.context = context ; } public void setExecutePool(ThreadPoolTaskExecutor executePool) { this.executePool = executePool; } }
package com.adai.asy.service.imp; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.adai.asy.service.AsyService; import com.adai.constant.Dict; /** * 异步服务接口实现类 * 这里主要时为了打印每一个任务需要执行的时间,正真执行业务逻辑的方法是executeInnert * @author v-chenk25 * */ public abstract class AsyServiceImp implements AsyService{ private Log log = LogFactory.getLog(AsyServiceImp.class) ; public void execute(Map<String,Object> sendMap) { long start = System.currentTimeMillis(); log.info("异步线程开始执行:"+sendMap.get(Dict.TASKID)+"任务"); executeInnert(sendMap) ; long end = System.currentTimeMillis(); log.info("异步线程执行结束,任务执行时间为:"+(end-start)); } /** 真正执行业务逻辑 **/ public abstract void executeInnert(Map<String,Object> sendMap); }
package com.adai.asy.service.imp; import java.util.Map; import org.springframework.stereotype.Service; import com.adai.asy.service.AsyService; /** * 需要异步执行任务的具体实现类 * @author v-chenk25 * */ @Service("myTaskAsyService1") public class MyTaskAsyServiceImp extends AsyServiceImp implements AsyService { @Override public void executeInnert(Map<String, Object> sendMap) { //做自己的业务逻辑处理 , 比如发银行的接口,调用dubbo服务 System.out.println(this.getClass().getName()); System.out.println(sendMap); } }
package com.adai.constant; /** * 常量字典 * @author v-chenk25 * */ public class Dict { /**交易流水号**/ public static final String ORDERID = "OrderId" ; /** 日期格式 **/ public static final String YND = "yyyyMMdd" ; /**时间戳格式**/ public static final String YNRH = "yyyyMMdd HH:mm:ss sss" ; /**时间格式**/ public static final String HOUR = "HH:mm:ss" ; /**交易id**/ public static final String TASKID = "taskId" ; }
package com.adai.util; import java.text.SimpleDateFormat; import java.util.Date; /** * 工具类 * @author v-chenk25 * */ public class Utils { /**当前日期指定格式字符串**/ public static String getCurrentFormat(Date date ,String format) { return new SimpleDateFormat(format).format(date); } }
package com.adai.asy.service.imp; import java.util.Map; import org.springframework.stereotype.Service; import com.adai.asy.service.AsyService; /** * 需要异步执行任务的具体实现类 * @author v-chenk25 * */ @Service("myTaskAsyService2") public class MyTaskAsyServiceImp2 extends AsyServiceImp imp afc8 lements AsyService { @Override public void executeInnert(Map<String, Object> sendMap) { //做自己的业务逻辑处理 System.out.println(this.getClass().getName()); System.out.println(sendMap); } }
package com.adai; import java.util.HashMap; import java.util.Map; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.adai.asy.service.AsyExecuteService; public class TestAsy { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"classpath:spring-activemq.xml"}) ; context.start(); AsyExecuteService asyService = (AsyExecuteService) context.getBean("asyExecuteService") ; for(int i=1 ; i<10 ;i++) { Map<String,Object> sendMap = new HashMap<String,Object>() ; sendMap.put(i+"", i) ; asyService.execute("myTaskAsyService"+1, sendMap); } } }总结:设计思路为:使用一个线程池开启一个线程去执行一个任务,任务id就是spring bean的名字,通ApplicationContextAware 来获取spring容器的bean,然后调用execute方法执行具体的业务逻辑。为了扩展,所以要求需要异步执行的类需要现实统一的接口,也就是AsyService接口。
相关文章推荐
- 为什么不建议在广播中启动一个线程做任务
- 使用Promise和async-await实现的一个异步遍历+同步执行任务的实例
- Thread Runnable建立新线程 Handler AsycTask执行异步任务(不一定建立新的线程)
- 一个线程执行多个任务,要按照顺序执行
- FutureTask的cancel方法真的能停止掉一个正在执行的异步任务吗
- 为什么不能直接在BroadCastReceiver中开一个线程执行耗时任务
- 一个线程执行完后,不删除它,再次执行怎样启动它?
- 为什么不建议在广播中启动一个线程做任务
- 使用 Task 替换 ThreadPool ,异步监测所有线程(任务)是否全部执行完毕
- 线程,是不是打破了“程序是顺序执行“的真谛?如一个main函数中,顺序定义了二个线程,并启动,第一个线程还没执行完,第二个线程就开始执行了
- 线程,任务,同步之异步执行和等待线程
- 关于多个异步任务线程如何取消上一个线程的问题
- JDK中的Timer和TimerTask详解 目录结构: Timer和TimerTask 一个Timer调度的例子 如何终止Timer线程 关于cancle方式终止线程 反复执行一个任务 sche
- 一个主线程下有多个子线程任务,主线程必须在100秒内将子线程执行的集合结果进行处理返回
- 多线程线程池控制一个方法的并发量 限制只有5个线程执行任务
- Android中使用Handler和异步任务(AsyncTack)来为UI线程执行费时操作
- springmvc怎么在启动时自己执行一个线程
- 两个线程A和B,任务都是打印当前时间,要求编码实现:线程A和B同时启动后,以先A后B的方式任务交叉执行10次。
- Android中使用Handler和异步任务(AsyncTack)来为UI线程执行费时操作
- 异步或多线程支持一个任务执行完成