Java异步方法调用

很多时候,我们需要调用一个耗时方法,但是我们并不需要等待它执行完,才继续后面的工作,阻塞在这里是一个非常浪费时间的事,那么我们有没有办法解决呢?有!让它异步执行!

首先我们先来看看不异步执行的方案,下面是伪代码

//我们需要执行的代码1
longTimeMethod();
//我们需要执行的代码2
如上,如果我们执行到longTimeMethod的时候,必须等待这个方法彻底执行完才能执行“我们需要执行的代码2”,但是如果二者的关联性不是那么强,其实是没有必要去等待longTimeMethod执行完的。

那么异步执行如何解决以上问题呢?

采用多线程把longTimeMethod 封装到一个多线程中,让它去执行
Thread t = new Thread(){
@Override
public void run() {
longTimeMethod();
}
};
采用Spring 的异步方法去执行
先把longTimeMethod 封装到Spring的异步方法中,这个方法一定要写在Spring管理的类中,注意注解@Async
@Service
public class AsynchronousService{
@Async
public void springAsynchronousMethod(){
longTimeMethod();
}
}
其他类调用这个方法。这里注意,一定要其他的类,如果在同类中调用,是不生效的。具体原因,可以去学习一下Spring AOP的原理
@Autowired
private AsynchronousService asynchronousService;

public void useAsynchronousMethod(){
//我们需要执行的代码1
asynchronousService.springAsynchronousMethod();
//我们需要执行的代码2
}
那么问题来了,以上异步调用的方法都是没有返回值的,如果有返回值的方法该怎么获取到返回值呢?

非异步的写法
//我们需要执行的代码1
Integer result = longTimeMethod();
//我们需要执行的代码2
采用JDK原生的Future类
//我们需要执行的代码1
Future future = longTimeMethod2();
//我们需要执行的代码2
Integer result = future.get();
可以看到,我们调用longTimeMethod2返回一个Future对象(注意了,这里的longTimeMethod2当然不是上面的longTimeMethod),然后处理“我们需要执行的代码2”,到了需要返回结果的时候直接调用future.get()便能获取到返回值。下面我们来看看longTimeMethod2如何实现。

private Future longTimeMethod2() {
//创建线程池
ExecutorService threadPool = Executors.newCachedThreadPool();
//获取异步Future对象
Future future = threadPool.submit(new Callable() {
@Override
public Integer call() throwsException {
return longTimeMethod();
}
});
return future;
}
可以看到我们用到了线程池,把任务加入线程池中,返回Future对象。其实我们调用longTimeMethod2方法是开启了其他的线程,其他的线程在调用工作。

对于Future来说,除了无参的get()方法之外,还有一个有参的get()方法。有参的get()方法中传入的参数是需要等待的时间,也就是超时设置,不需要一直等待下去。而我们返回的Future对象是FutureTask的实例。

采用Spring的异步方法执行
先把longTimeMethod 封装到Spring的异步方法中,这个异步方法的返回值是Future的实例。这个方法一定要写在Spring管理的类中,注意注解@Async。
@Service
public class AsynchronousService{
@Async
public Future springAsynchronousMethod(){
Integer result = longTimeMethod();
return new AsyncResult(result);
}
}
其他类调用这个方法。这里注意,一定要其他的类,如果在同类中调用,是不生效的。
@Autowired
private AsynchronousService asynchronousService;

public void useAsynchronousMethod(){
Future future = asynchronousService.springAsynchronousMethod();
future.get(1000, TimeUnit.MILLISECONDS);
}
其实Spring只不过在原生的Future中进行了一次封装,我们最终获得的还是Future实例。

链接:https://www.jianshu.com/p/51f0555b232a

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值