`
glsjay
  • 浏览: 10790 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Spring @Async 中Future的使用

阅读更多
这半年来一直组里的项目基本架构是Spring MVC,从中学到的不少关于Spring尤其是Annotation的使用,最近碰到的一个问题是在Spring中做Multi-threading的问题,其实如果没有在框架里做multi-threading是一个很Core java的知识点,无非是用runnable用Thread然后加上那几个wait,join,sleep等等方法。然而经过测试发现Spring偏偏有是有默认的执行顺序,不受外界这些个线程的方法的影响,可能跟Spring创建的bean的scope有关系,要改的的话可能有办法,类似于在annotation里改个什么变量,或是config文件里改个什么bean的创建设置或属性,但由于并不想改太多的现有框架结构和业务流程,所以对Spring本身自带的multi-threading的功能进行了一个小粗浅的研究和运用。

主要就是@Async这个annotation的使用,由于编程都是完成功能为目的,所以只是基于这次的任务使用到了的部分进行展示,深的东西没有过多追究。

首先要用到这个annotation,前提Spring的各种环境配置一定是要弄好的,在context config要加上annotation driven的config bean,要在web.xml注册好Spring的listener什么的就不说了,还不会的可以自己搜搜到处都是,然后就是在一个bussiness bean里使用了,举例说明,比如一个service类,有一个方法是向调用DAO进而向database发出query,如下

public class QueryService{
	private QueryDao query;
	
	public Object doQuery(String queryName){		
		return query.getQuery();
	}
	
}



如果用到Spring对这个bean inject基础上,要加入multi-threading就不那么直接了,如果再用core java 那一套Spring会无视之,所以要在方法上面加上一个@Async,如下:


@Service
public class QueryService{
	private QueryDao query;
	
      @Async
	public Object doQuery(String queryName){		
		return query.getQuery();
	}
	
}



这样做就能使多次的调用成为多线程同步执行了,然而测试发现,标注@Async的方法只能在别的类里被调用才能实现多线程,鉴于此,我们最好是新建一个Wrapper类去实现,把这个类做为如果要使用多线程时才调用的类

@Service
public class QueryWrapper{
        private QueryService queryService;
	
     @Async
     public Object doQueryAsych(String queryName){	
              try {   
                 Thread.sleep(15000);   
              } catch (InterruptedException e) {   
                 e.printStackTrace();   
              }  	
	     return queryService.doQuery();
	}
	
}


别忘记了在context里加上Spring的task管理bean,可以对thread pool的大小等等去设置
<task:annotation-driven executor="executor" />
<task:executor id="executor" pool-size="7"/>


到这一步,基本就能利用Spring的多线程管理调用了,但只是单纯的多线程执行一个无返回值的的方法,接下来的问题就是对方法返回值的处理了,怎么去实现callback的功能,这时就要用到Future接口了,这个接口在java.util.concurrent.Future;里,以及Future类的实现类AsyncResult<T>,道理很明显,就是把原本的返回值用AsyncResult来注册返回,再用futurn.get();这个方法去等待返回值的,所谓的callback就完成了,下面的代码是调用上述的wrapper类中的方法对返回值的收集处理:


public class Helper{
     private QueryWrapper wrapper;
	
	  public List<Object> getObject(String[] queryNames){
	        List<Object> result = new ArrayList<Object>();

            List<Future<Object>> futures = new ArrayList<Future<Object>>();
             
            //get each future object after firing the 
            for(String queryName : queryNames){
                 future.add(wrapper.doQueryAsych(queryName ));
            }
            //call back part
            for(String future : futures){
                 //wait future's return value and add into result list
                 result(future.get());
            }

            return result;
        }
}



code都是我手敲的,如果有typo请别喷,基本原理就是这样,用Future作为callback的载体,用futurn.get()这个方面去等待并得到各个不同线程返回的的值,核心点就是这么多,接下来就是要完善一下代码就行了。

希望对你有帮助


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics