spring @Async 简单学习

在看spring reference的时候看到spring 中关于异步task的封装,感觉很有意思,试了一下。

简单的说,spring 对java的TaskExecutor进行了封装,可以像pojo一样使用,事实上,我们也可以直接使用TaskExecutorService(如果我没有记错,java里是这个类吧),当然也可以自己实现,但spring提供了一些类,比如ThreadPoolTaskExecutor,为什么不使用呢?当然更重要的是它在配置文件中提供了一种简便方式<task-excutor/>,就相当于声明了一个ThreadPoolTaskExecutor的bean。接下来一步步开始实验。

1, 首先在context.xml中做一些声明,配置ThreadPoolTaskExecutor,以及使用anotation driven

<context:component-scan base-package="test" />
<task:executor id="myExecutor" pool-size="2" />
<task:annotation-driven executor="myExecutor" />

2, 编写需要异步执行的代码。

@Async
	public Future do()  {
		........		
		return new AsyncResult(...);
	}

 这个地方是使我很吃惊的地方。这里只需要做两件事,annotate这个方法为@Async,以及让这个方法返回Future对象(如果这个方法不需要返回值,那这个也不需要,只需要返回void)。而且事实上如果需要传入参数,也可以像其他的方法一样传入。按照文档上说,这样做了以后,当我们调用这个方法以后,会直接返回,但是需要body部分会异步执行,我们所要做的,只需要等在Future.get()上就可以了。神奇吧?

3, 接下来就像其他的bean一样了,caller和callee,通过context得到,就像调用普通方法一样调用就可以了。

4, 一些问题

    当然也遇到了一些问题,不然就像上面简单罗列一下,还不如直接把文档里copy过来。

    a, 一开始,我直接把这个异步方法放在main() (main用来启动context).所在的类里, 结果发现,这个方法事实上没有在异步执行。我搜了一些资料,发现做法和我差不了多少。这种简单的应用spring应该不会有问题吧?我想到spring肯定是要为这个方法生成proxy,它只是替我们做了很多生成thread,future的事情,也许问题出在spring不能为main所在的类生成proxy上面,或者至少是不能为这样的异步方法生成proxy。我把这个方法移到一个新的类中去以后,果然就成功了。当然可能还有更detail的原因。

    b, 按a做了以后很happy。但等程序执行以后,这种happy慢慢地没有了,因为我发现程序过了很久都没有结束。又过了很久还是没有结束(我是用eclipse执行的,从console状态可以看出程序仍然在运行)。我猜这种情况应该是因为那两个异步的任务没有结束掉造成的。我用jconsole查看了一下,果然发现那个异步线程wait中,main线程已经结束了。郁闷。如果是我们自己写的thread,任务完成后自然会停掉,但spring替我们生成的线程还要我们去管理,这个太不爽了。但好在还是有办法处理。就是通过context得到threadPoolTaskExecutor,然后调用destroy方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值