Java异步方法调用

作者: 迦若莹 | 来源:发表于2017-12-03 10:29 被阅读47次

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

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

//我们需要执行的代码1
longTimeMethod();
//我们需要执行的代码2

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

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

  • 采用多线程把longTimeMethod 封装到一个多线程中,让它去执行
Thread t = new Thread(){
  @Override
  public void run() {
    longTimeMethod();
  }
};
  • 采用Spring 的异步方法去执行
  1. 先把longTimeMethod 封装到Spring的异步方法中,这个方法一定要写在Spring管理的类中,注意注解@Async
@Service
public class AsynchronousService{
  @Async
  public void springAsynchronousMethod(){
    longTimeMethod();
  }
}
  1. 其他类调用这个方法。这里注意,一定要其他的类,如果在同类中调用,是不生效的。具体原因,可以去学习一下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的异步方法执行
  1. 先把longTimeMethod 封装到Spring的异步方法中,这个异步方法的返回值是Future的实例。这个方法一定要写在Spring管理的类中,注意注解@Async。
@Service
public class AsynchronousService{
  @Async
  public Future springAsynchronousMethod(){
    Integer result = longTimeMethod();
    return new AsyncResult(result);
  }
}
  1. 其他类调用这个方法。这里注意,一定要其他的类,如果在同类中调用,是不生效的。
@Autowired
private AsynchronousService asynchronousService;

public void useAsynchronousMethod(){
    Future future = asynchronousService.springAsynchronousMethod();
    future.get(1000, TimeUnit.MILLISECONDS);
}

其实Spring只不过在原生的Future中进行了一次封装,我们最终获得的还是Future实例。

相关文章

  • 实现异步转同步

    极客时间-《Java并发编程实战》学习笔记 异步方法:调用方法,在方法中启动子线程异步调用:启动子线程调用方法异步...

  • Java异步方法调用

    很多时候,我们需要调用一个耗时方法,但是我们并不需要等待它执行完,才继续后面的工作,阻塞在这里是一个非常浪费时间的...

  • 10.5 WebView与js交互

    Java调用JS evaluateJavascript:专门用于异步调用JavaScript方法,并且能够得到一个...

  • 异步任务执行的设计模式

    参考:java的设计模式 异步执行方法回调的设计模式:异步方法调用是在等待任务结果时不阻塞调用线程的模式。该模式提...

  • java 异步调用方法

    异步方法 其他方法要使用异步时,直接调用fun()方法即可

  • 2018-03-13 Spring中的异步调用

    异步方法调用 异步方法调用或异步方法模式是(多线程)面向对象程序设计中用于异步调用对象的潜在的长期运行方法的一种设...

  • Java多线程--基础概念

    Java多线程--基础概念 必须知道的几个概念 同步和异步 同步方法一旦开始,调用者必须等到方法调用返回后,才能执...

  • 并发编程的一些概念

    同步:同步方法调用一旦开始,调用者必须等到方法调用返回,才能继续后续的工作。 异步:异步方法就不需要等到方法调用返...

  • Spring中使用@Async异步调用方法

    摘要 异步调用传统SSM项目实现 异步调用SpringBoot实现 Async简介: 异步方法调用使用场景:处理日...

  • Java8——异步编程

    Java8——异步编程 异步编程 所谓异步其实就是实现一个无需等待被调用函数的返回值而让操作继续运行的方法 创建任...

网友评论

    本文标题:Java异步方法调用

    本文链接:https://www.haomeiwen.com/subject/sdlabxtx.html