springboot-33-异步方法和dubbo异步调用

一.Spring @Async异步方法

在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的;但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3.x之后,就已经内置了@Async来完美解决这个问题。

  1. 何为异步调用?

    在解释异步调用之前,我们先来看同步调用的定义;同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕;而是继续执行下面的流程。

    例如, 在某个调用中,需要顺序调用 A, B, C三个过程方法;如他们都是同步调用,则需要将他们都顺序执行完毕之后,方算作过程执行完毕; 如B为一个异步的调用方法,则在执行完A之后,调用B,并不等待B完成,而是执行开始调用C,待C执行完毕之后,就意味着这个过程执行完毕了。

2. 常规的异步调用处理方式

在Java中,一般在处理类似的场景之时,都是基于创建独立的线程去完成相应的异步调用逻辑,通过主线程和不同的线程之间的执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。

3. @Async介绍

在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。这里的dubbo是同步接口。

@Service
public class AsyncMyService {
    @Reference(version = "1.0.0")
    private IDubboDemoService dubboDemoService;

    @Async
    public Future<String> hello(String name) throws MyException {
        AsyncResult<String> result = new AsyncResult<>(dubboDemoService.sayHello(name));
        return result;
    }
}
  1. 返回类型

需要注意的异步调用的返回是AsyncResult,而要想获得返回则需要通过future.get()。获取异步方法的结果信息,是通过不停的检查Future的状态来获取当前的异步方法是否执行完毕来实现的。


@Test
public void testAsync() {
   Future<String> result = null;
   try {
      result = asyncMyService.hello("asd");
      String str = result.get();
      System.out.println("Result from asynchronous process - " + str);
   } catch (Exception e) {
      e.printStackTrace();
   }
}

这样看更加明显一些:

@Test
public void testAsync() {
   Future<String> result = null;
   try {
      result = asyncMyService.hello("asd");

      while (true) {  ///这里使用了循环判断,等待获取结果信息
         if (result.isDone()) {  //判断是否执行完毕
            System.out.println("Result from asynchronous process - " + result.get());
            break;
         }
         System.out.println("Continue doing something else. ");
         Thread.sleep(500);
      }
   } catch (Exception e) {
      e.printStackTrace();
   }
}
 

二、异步dubbo

可能还会有这样一种场景,我们在调用dubbo时,不关心其返回值(有点像mq的使用方式),此时就可以用到dubbo异步方法。Dubbo异步方法基于NIO的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小。

springboot-33-异步方法和dubbo异步调用

  1.   服务提供方
    

注解的方法非常简单,在服务提供方配置如下:@Service(version=“1.0.0”, async = true)

@Service(version="1.0.0", async = true)
public class DubboDemoServiceImpl implements IDubboDemoService {
    @Resource(name = "producer")
    private Producer producer;

    @Resource(name = "myTopic")
    private ActiveMQTopic myTopic;


    @Override
    public String sayHello(String name) throws MyException {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if(name.equals("Tom")) {
            throw new RuntimeException("The Name is Tom! He is not a good man!");
        }
        producer.send(myTopic, "heheda");
        return "hello " + name;
    }

    @Override
    public String sayYourAge(int age) throws MyException{
        return null;
    }
}
 
  1.   服务消费方:@Reference(version = "1.0.0",async = true)
    

@Service
public class MyService {
    @Reference(version = "1.0.0", async = true)
    private IDubboDemoService dubboDemoService;

    public String hello(String name) throws MyException {
        String result = dubboDemoService.sayHello(name);
        return result;
    }
}
 
  1.   完全不理会返回
    

按照以上两步,可以实现dubbo服务的异步调用,但是会发现在服务端报错:

Caused by: java.nio.channels.ClosedChannelException: null。

要想消除这种错误,注解就无能为力了,必须使用xml,使得dubbo异步方法的返回为false。

此时完全忽略返回值,可以配置return=“false”,以减少Future对象的创建和管理成本:

<dubbo:method name=“findFoo” async=“true” return=“false” />

参考:
http://blog.csdn.net/chenaini119/article/details/51850526
http://dubbo.io/user-guide/demos/异步调用.html
http://www.cnblogs.com/lcngu/p/6185363.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值