使用线程池和反射实现异步任务
2016-09-22 10:34
597 查看
很久没来写东西了,冠冕堂皇的原因就是太忙了,这一年时间负责技术还要负责产品,带领三五个小伙伴做一个互联网系统,实在是累。实际的原因就是太懒了,每次想写点什么,却总是在犹豫中蹉跎。
最近写了一点代码,和大家分享交流。主要应用场景就是在把业务流程中某些不是太重要却又比较耗时的任务从主流程剥离放到线程池去执行,但这样的场景很多,很分散,又不想为每个场景写专门的处理类,就想使用反射偷点懒,每个被剥离的任务只需要实现一个方法就可以,而不用实现一个类。
调度类实现了一个线程池的调度,大概关键代码如下:
任务主体类如下:
SpringHelper是我项目里实现的一个工具类,用于根据名字查找spring注入的实体对象。
调用方式:
如果需要使用任务的执行结果,则可以这样:
最近写了一点代码,和大家分享交流。主要应用场景就是在把业务流程中某些不是太重要却又比较耗时的任务从主流程剥离放到线程池去执行,但这样的场景很多,很分散,又不想为每个场景写专门的处理类,就想使用反射偷点懒,每个被剥离的任务只需要实现一个方法就可以,而不用实现一个类。
调度类实现了一个线程池的调度,大概关键代码如下:
public class Scheduler { private static final Log logger = LogFactory.getLog(Job.class); private static final Scheduler instance = new Scheduler(); private static ExecutorService executorServie; private Scheduler() { executorServie = Executors.newFixedThreadPool(10); } @Bean(name = "Bmall.Scheduler", initMethod = "init", destroyMethod = "shutdown") public static Scheduler getInstance() { return instance; } public void init() { if (start) { this.start(); } } public void shutdown() { .... } /** * 调用一个任务,返回FutureTask * @param service 可以是bean的名字也可以是bean对象<br/> * @param method 需要执行的方法名<br/> * @param params 执行所需参数<br/> * @return FutureTask对象 * @throws InterruptedException * @throws ExecutionException */ public <T> FutureTask<T> call(T service, String method,@SuppressWarnings("unchecked") T ... params) throws InterruptedException, ExecutionException{ FutureTask<T> futureTask = new FutureTask<T>(new AloneTask<T>(service,method,params)); executorServie.submit(futureTask); return futureTask; } }
任务主体类如下:
public class AloneTask<T> implements Callable<T> { private static final Log logger = LogFactory.getLog(AloneTask.class); Object service; String method; Object[] params; public AloneTask(T service, String method,Object ... params) { super(); if(service instanceof String){ this.service=(Object) SpringHelper.getBean((String) service); }else{ this.service = service; } this.method = method; this.params = params; } @Override @SuppressWarnings("unchecked") public T call() throws Exception { // TODO Auto-generated method stub if(service==null||method==null){ ExceptionHelper.throwExcep("参数异常,无法完成任务."); } long startTime = System.currentTimeMillis(); T future=(T) getMethod().invoke(this.service, this.params); long useTime = (startTime - System.currentTimeMillis()) / 1000; if(useTime > 10) { logger.warn("call cost time too long,time "+useTime+"s,task method:" + this.method); } return future; } /* * 获取被调用的方法 */ private Method getMethod(){ Method m=null; try { @SuppressWarnings("rawtypes") Class[] paramsClass = new Class[this.params.length]; for(int i=0;i<this.params.length;i++){ paramsClass[i]=this.params[i].getClass(); } m=this.service.getClass().getMethod(this.method, paramsClass); } catch (Exception e) { // TODO Auto-generated catch block logger.info(String.format("not find [%s] method,try scan all method ...",this.method)); Method[] allMethods=this.service.getClass().getMethods(); for(Method mRec:allMethods){ if(mRec.getName().equals(this.method)){ Class<?>[] methodParamsTypes = mRec.getParameterTypes(); //找到同名函数的参数类型 if(methodParamsTypes.length==this.params.length){ boolean flag=true; for(int i=0;i<methodParamsTypes.length;i++){ if(null!=this.params[i]){ if(!match(this.params[i],methodParamsTypes[i])){ flag=false; break; } } } if(flag){ m=mRec; break; } } } } } if(null==m){ ExceptionHelper.throwExcep(String.format("未找[%s]到的[%s]方法完成任务.",this.service.getClass().toString(),this.method)); } return m; } /** * 判断参数类型是否匹配 * @param c 参数类型 * @param pc 方法参数类型 * @return */ private boolean match(Object p,Class pc){ boolean isMatch=true; if(pc.isPrimitive()){ //方法参数是基本类型 if(!pc.equals(getPrimitiveClass(p.getClass()))){ isMatch=false; } }else{ if(!pc.isInstance(p)){ isMatch=false; } } return isMatch; } private static Class getPrimitiveClass(Class c) { Class pc = null; if( c.equals(Long.class) ) { pc = long.class; } else if( c.equals(Integer.class) ) { pc = int.class; } else if( c.equals(Double.class) ) { pc = double.class; } else if( c.equals(Float.class) ) { pc = float.class; } else if( c.equals(Short.class) ) { pc = short.class; } else if( c.equals(Byte.class) ) { pc = byte.class; } else if( c.equals(Character.class) ) { pc = char.class; } else if( c.equals(Boolean.class) ) { pc = boolean.class; } return pc; } }
SpringHelper是我项目里实现的一个工具类,用于根据名字查找spring注入的实体对象。
调用方式:
Scheduler.getInstance().call(obj, method, params);
如果需要使用任务的执行结果,则可以这样:
... FutureTask<String> rs = Scheduler.getInstance().call(obj, method, params); //执行主线程的任务 doSomething(); ... ... //获取任务结果,如果没有结果返回,则会阻塞等待返回 rs.get();
相关文章推荐
- 使用线程池实现异步打日志和存库的任务调度
- 在tornado中使用celery实现异步任务处理之一
- android利用线程池高效实现异步任务
- Android使用线程池处理异步任务
- 使用C++11实现一个半同步半异步线程池
- 性能优化之使用线程池处理异步任务
- 在tornado中使用celery实现异步任务处理之二
- Android性能优化之使用线程池处理异步任务
- Android性能优化之使用线程池处理异步任务
- Android 性能优化之使用线程池处理异步任务
- 使用C++11实现一个半同步半异步线程池
- Android使用自己封装的Http和Thread、Handler实现异步任务
- Android性能优化之使用线程池处理异步任务
- Android性能优化之使用线程池处理异步任务
- 在tornado中使用celery实现异步任务处理之中的一个
- java中基于线程池和反射机制实现定时任务
- android利用线程池高效实现异步任务
- Android性能优化之使用线程池处理异步任务
- Android性能优化之使用线程池处理异步任务
- 解析C#多线程编程中异步多线程的实现及线程池的使用