精华内容
下载资源
问答
  • 异步调用

    千次阅读 2017-09-14 17:17:16
    异步调用:上述场景中,若B为一个异步的调用方法,则在执行完A之后,调用B,并不等待B完成,而是开始调用C,待C执行完毕之后,就意味着这个过程执行完毕了,不需要等待B方法的处理结果 方案 方案一:Java ...

    场景

    串行调用:在某个调用中,需要顺序调用 A, B, C三个过程方法,且是同步调用,则需要将三个方法都顺序执行完毕之后,整个调用过程执行完毕

    异步调用:上述场景中,若B为一个异步的调用方法,则在执行完A之后,调用B,并不等待B完成,而是开始调用C,待C执行完毕之后,就意味着这个过程执行完毕了,不需要等待B方法的处理结果

    方案

    方案一:Java Future、ThreadPoolExecutor 来实现(有返回值用callable、无返回值用runnable)

    方案二:Guava 中 AsyncEventBus

    示例:

    import com.google.common.eventbus.AllowConcurrentEvents;
    import com.google.common.eventbus.AsyncEventBus;
    import com.google.common.eventbus.Subscribe;
     
    import java.util.concurrent.Executors;
     
    /**
     * Created by zhuqiuhui on 2017/9/13.
     */
    public class AsyncTest {
     
        public static void main(String[] args) throws InterruptedException {
            AsyncEventBus asyncEventBus = new AsyncEventBus(Executors.newFixedThreadPool(3));
            asyncEventBus.register(new Object(){
     
                @AllowConcurrentEvents
                @Subscribe
                public void handleStringEvent(String s) throws InterruptedException {
                    Thread.sleep(3000);
                    System.out.println(s);
    //                int test = 4/0;
                    throw new NullPointerException();
                }
     
                @AllowConcurrentEvents
                @Subscribe
                public void handleIntegerEvent(Integer i) throws InterruptedException {
                    Thread.sleep(1000);
                    System.out.println(i);
                    throw new IllegalStateException();
                }
     
            });
            asyncEventBus.post("这是个测试");
            asyncEventBus.post(4);
            System.out.println("继续主函数......");
            Thread.sleep(5000);
            System.out.println("主函数结束......");
        }
    }

    输出:

    继续主函数......
    4
    九月 132017 5:05:42 下午 com.google.common.eventbus.EventBus$LoggingSubscriberExceptionHandler handleException
    严重: Could not dispatch event: service.AsyncTest$1@6fb554cc to public void service.AsyncTest$1.handleIntegerEvent(java.lang.Integer) throws java.lang.InterruptedException
    九月 132017 5:05:44 下午 com.google.common.eventbus.EventBus$LoggingSubscriberExceptionHandler handleException
    这是个测试
    严重: Could not dispatch event: service.AsyncTest$1@6fb554cc to public void service.AsyncTest$1.handleStringEvent(java.lang.String) throws java.lang.InterruptedException
    主函数结束......

    由上可以看出,已经注册的方法的状态不影响主流程,适合异步场景。

    注意:Guava EventBus中默认订阅方法为线程不安全的,在异步调度时会自动将其包装成线程安全的方法。对于一般线程安全的实现上,可以通过@AllowConcurrentEvents注解来标识。

    方案三:Spring 中 @Async 注解

     

    applicationContext.xml
    <task:annotation-driven executor="annotationExecutor" />
    <!-- 支持 @Async 注解 -->
    <task:executor id="annotationExecutor" pool-size="20"/>
    AsynServiceProxy.java
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.scheduling.annotation.AsyncResult;
    import org.springframework.stereotype.Component;
     
    import java.util.concurrent.Future;
     
    /**
     * Created by zhuqiuhui on 2017/9/14.
     */
    @Component
    public class AsynServiceProxy {
     
        @Async
        public Future<String> testSpringAsync01(String s) {
            try {
                Thread.sleep(7000);
            catch (InterruptedException e) {
                e.printStackTrace();
            }
     
            System.out.println(s);
            return new AsyncResult<>("这是返回结果");
        }
    }
      

    异步方法必须单独写一个类中

    @Service
    public class PromotionServiceImpl implements IPromotionService {
        @Resource
        private AsynServiceProxy asynServiceProxy;
      
        @Override
        public void testAsyncMethod(){
            Future<String> s = asynServiceProxy.testSpringAsync01("test");
     
            System.out.println("继续主函数......");
            System.out.println("主函数结束......");
     
     
            try {
                System.out.println(s.get() + "---------");
            catch (InterruptedException e) {
                e.printStackTrace();
            catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }

    输出结果:

    输出结果
    继续主函数......
    主函数结束......
    test
    这是返回结果---------

    s.get() 等待线程的结束,取得返回值。

    陷阱一:Spring @Async circular reference (在方法中添加@Async出现循环依赖问题)

    如service类中加:

    @Service
    public class PromotionServiceImpl implements IPromotionService {
        @Resource
        private IPromotionRuleService iPromotionRuleService;
     
        @Override
        @Async
        public void testAsync(String s) {
            try {
                Thread.sleep(7000);
            catch (InterruptedException e) {
                e.printStackTrace();
            }
     
            System.out.println(s);
        }
    }

    原因:准备注入的 bean,已经是代理 bean,而不是原始 bean。

    解决办法:单独写一个代理 bean,存放异步方法,并且代理 bean 中,不再依赖注入自身 bean。

    注意:在同一个类中,一个方法调用另外一个有@Async注解的方法,注解是不会生效的。因为spring 在扫描包的时候,如果发现类或类中有方法有@Asycn注解,spring会为这个bean动态地生成一个代理类。当方法被调用时,实际是调用代理类的。然而,如果这个有@Async的方法是被同一个类中的其他方法调用的,那么该方法的调用就没有通过代理类,而是直接通过原来的那个bean,所以就不会启动新线程异步调用。

    展开全文
  • 要在springboot中使用异步调用方法,只要在被调用的方法上面加上@Async就可以了 1.准备工作 准备一个springboot工程,在Application类上加上EnableAsync注解开启异步 /** * @Author: zgd * @Date...

    Page Counter

    一. springboot的@Async注解实现异步

    要在springboot中使用异步调用方法,只要在被调用的方法上面加上@Async就可以了

    1.准备工作

    准备一个springboot工程,在Application类上加上EnableAsync注解开启异步

    /**
     * @Author: zgd
     * @Date: 18/09/12 10:27
     * @Description:
     */
    @SpringBootApplication
    @EnableAsync
    public class Application {
    
      public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
      }
    
    }
    

    这个注解如果不加,@Async注解失效

    2.controller

    写一个同步接口和异步接口

    package com.zgd.demo.thread.asyn.controller;
    
    import com.zgd.demo.thread.asyn.service.HelloService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.time.Instant;
    
    /**
     * @Author: zgd
     * @Date: 18/09/12 10:26
     * @Description: hello
     */
    @RestController
    @RequestMapping("/hello")
    public class HelloController {
    
      @Autowired
      private HelloService helloService;
    
      /**
       * 异步方法
       * @return
       */
      @RequestMapping("/asyn")
      public String getAsynHello(){
        long n = Instant.now().toEpochMilli();
        //异步
        String s = helloService.asynchSayHello();
    
        long f = Instant.now().toEpochMilli();
        return s + " 时间: " + (f-n);
    
      }
    
      /**
       * 同步方法
       * * @return
       */
      @RequestMapping("/sync")
      public String getSyncHello(){
    
        long n = Instant.now().toEpochMilli();
        //异步
        String s = helloService.synchSayHello();
    
        long f = Instant.now().toEpochMilli();
        return s + " 时间: " + (f-n);
      }
    }
    

    3.helloService

    写一个HelloService接口,并实现该接口

    package com.zgd.demo.thread.asyn.service.impl;
    
    import com.zgd.demo.thread.asyn.service.HelloService;
    import com.zgd.demo.thread.asyn.service.SleepService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * @Author: zgd
     * @Date: 18/09/12 10:43
     * @Description:
     */
    @Service
    public class HelloServiceImpl implements HelloService {
    
      @Autowired
      private SleepService sleepService;
    
      @Override
      public String synchSayHello() {
        try {
          sleepService.syncSleep();
          return "hello world,这是同步方法";
        } catch (InterruptedException e) {
          e.printStackTrace();
          return "error";
        }
      }
    
      @Override
      public String asynchSayHello() {
        try {
          System.out.println("主线程 "+Thread.currentThread().getName());
          sleepService.asyncSleep();
          return "hello world,这是异步方法";
        } catch (InterruptedException e) {
          e.printStackTrace();
          return "error";
        }
      }
    }
    

    这里为了模拟应用场景,将耗时的方法放在另一个service里面,就叫SleepService,同样的,实现这个接口

    package com.zgd.demo.thread.asyn.service.impl;
    
    import com.zgd.demo.thread.asyn.service.SleepService;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Service;
    
    /**
     * @Author: zgd
     * @Date: 18/09/12 10:46
     * @Description:
     */
    @Service
    public class SleepServiceImpl implements SleepService {
    
      @Override
      public void syncSleep() throws InterruptedException {
        System.out.println("线程名: " +Thread.currentThread().getName());
        System.out.println("开始同步休眠3秒");
        Thread.sleep(3000);
        System.out.println("同步休眠结束");
      }
    
      @Override
      @Async
      public void asyncSleep() throws InterruptedException {
        System.out.println("次线程 "+Thread.currentThread().getName());
    
        System.out.println("开始异步休眠3秒");
        Thread.sleep(3000);
        System.out.println("异步休眠休眠结束");
      }
    }
    
    

    两个方法都是休眠3秒,aysncSleep方法上面有一个@Async注解

    4.测试

    • 同步
      访问 http://localhost:8080/hello/sync
      在这里插入图片描述
      控制台
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kpLDV4Mc-1587893525642)(https://i.imgur.com/aICMDZA.png)]
      要3秒的时间才能收到响应

    • 异步
      访问 http://localhost:8080/hello/asyn
      在这里插入图片描述
      在这里插入图片描述
      可见主线程和次线程打印出来的线程名不一样,也就是springboot帮我们开启了一个线程去处理

    注意事项

    1. 必须要加@EnableAsync注解
    2. 不能在同一类下调用@Async注解的方法,比如A类下有a和b方法,b方法有@Async注解,不能直接这样a调用b,要把b放到其他类中
    3. @Async也可以打在类上,这样类下面的所有方法都是异步的(被其他类调用的时候)

    二.开启线程实现异步

    如果我们没有使用springboot,使用传统的方法怎么异步调用方法?还是开启一个新的线程

    1.controller

    增加一个接口

    /**
       * 同步方法
       * * @return
       */
      @RequestMapping("/thread/asyn")
      public String getThreadSyncHello(){
        long n = Instant.now().toEpochMilli();
        //异步
        String s = helloService.threadAsynchSayHello();
        long f = Instant.now().toEpochMilli();
        return s + " 时间: " + (f-n);
      }
    
    

    2.service

    HelloServiceImpl

    @Override
      public String threadAsynchSayHello() {
        //还是休眠3秒
        Runnable runnable = ()-> {
          try {
            sleepService.syncSleep();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        };
        System.out.println(Thread.currentThread().getName()+"  开启新线程");
        new Thread(runnable).start();
        return "hello world,这是开启线程的异步方法";
      }
    

    3.测试

    我们访问 http://localhost:8080/hello/thread/asyn
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aqsAimN4-1587893525654)(https://i.imgur.com/huTAJAm.png)]

    在这里插入图片描述

    同样的两个线程名不一样,开启了一个新线程处理,并且多次测试可以看出,自己直接开启线程比@Async要快几毫秒,不过可以忽略不计了

    展开全文
  • Dubbo异步调用

    千次阅读 2020-04-15 15:12:42
    异步调用, 对于 Provider 端不需要做特别的配置。 Consumer 配置: <dubbo:reference id="asyncService" interface="com.x.x.AsyncService"> <dubbo:method name="testAsync" async="true"/> <...

    异步调用,

    对于 Provider 端不需要做特别的配置。

    Consumer 配置:

    <dubbo:reference id="asyncService" interface="com.x.x.AsyncService">
        <dubbo:method name="testAsync" async="true"/>
    </dubbo:reference>

    Consumer 端发起调用:

    String result = asyncService.testAsync("samples");// 这里的返回值为空,请不要使用
    Future<String> future = RpcContext.getContext().getFuture();
    ... // 业务线程可以开始做其他事情
    result = future.get(); // 阻塞需要获取异步结果时,也可以使用 get(timeout, unit) 设置超时时间


    Dubbo Consumer端发起调用后,同时通过RpcContext.getContext().getFuture()获取跟返回结果关联的Future对象,然后就可以开始处理其他任务;当需要这次异步调用的结果时,可以在任意时刻通过future.get(timeout)来获取。

    一些特殊场景下,为了尽快调用返回,可以设置是否等待消息发出:

    sent="true" 等待消息发出,消息发送失败将抛出异常;
    sent="false" 不等待消息发出,将消息放入 IO 队列,即刻返回。
    return="false" 完全忽略是否返回

    <dubbo:method name="testAsync" async="true" sent="true" />
    或者
    <dubbo:method name="testAsync" async="true" return="false"/>

    默认是sent="false"。

    展开全文
  • 同步调用与异步调用

    千次阅读 2018-09-11 11:02:33
    同步调用和异步调用是两种提交任务的方式 同步调用:提交完任务后,就在原地等待任务执行完毕,拿到运行结果/返回值后再执行下一步,同步调用下任务是串行执行。 异步调用:提交完任务后,不会再原地等待任务执行...

    同步调用和异步调用是两种提交任务的方式

    同步调用:提交完任务后,就在原地等待任务执行完毕,拿到运行结果/返回值后再执行下一步,同步调用下任务是串行执行。

    异步调用:提交完任务后,不会再原地等待任务执行完毕,直接执行下一行代码,异步调用时并发执行。

    异步调用,几乎同时下达任务

    from concurrent.futures import ProcessPoolExecutor
    import os, time,random
    
    
    
    def task(x):
        print("%s is running" % os.getpid())
        time.sleep(random.randint(1,3))
        return x**2
    
    if __name__=="__main__":
        p = ProcessPoolExecutor()
        futures = []
        for i in range(10):
            future = p.submit(task,i)#返回计算结果
            futures.append(future)
        p.shutdown(wait=True)#默认waiti为True 等待十个进程任务执行完,关闭进程池的入口。
        for future in futures:
            print(future.result())
        print("主")
    结果为:
    
    10760 is running
    10564 is running
    12848 is running
    3928 is running
    10564 is running
    12848 is running
    10760 is running
    3928 is running
    10760 is running
    10564 is running
    0
    1
    4
    9
    16
    25
    36
    49
    64
    81
    主

    如果把p.shutdown(wait=True)去掉,则会出现结果穿插在进程中

    2908 is running
    8092 is running
    10376 is running
    13136 is running
    8092 is running
    2908 is running
    0
    1
    8092 is running
    10376 is running
    4
    2908 is running
    10376 is running
    9
    16
    25
    36
    49
    64
    81
    主

     

    同步调用:

    def task(x):
        print("%s is running" % os.getpid())
        time.sleep(random.randint(1,3))
        return x**2
    
    if __name__=="__main__":
        p = ProcessPoolExecutor()
        for i in range(10):
            res = p.submit(task,i).result()#返回计算结果
            print(res)
        print("主")
    
    结果为:
    
    8360 is running
    0
    472 is running
    1
    4888 is running
    4
    12980 is running
    9
    8360 is running
    16
    472 is running
    25
    4888 is running
    36
    12980 is running
    49
    8360 is running
    64
    472 is running
    81
    主

    串行执行,效率低下。

    展开全文
  • Vue中的同步调用和异步调用

    千次阅读 2020-03-03 11:26:54
    Promise实现异步调用 异步调用,增加a、b两个方法,并在mounted中调用。 观察客户端,并没有按照方法执行的顺序输出,使用Promise实现了异步调用。 观察客户端,并没有按照方法执行的顺序输出,使用Promise实现了...
  • java实现异步调用

    万次阅读 2020-07-21 17:21:02
    1、使用线程池的逻辑实现异步调用 package com.ourlang.dataextract.controller; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.ourlang.dataextract.common.CommonResult; import ...
  • C 异步调用

    千次阅读 2019-02-07 09:23:47
    C 异步调用
  • Java 实现异步调用

    万次阅读 热门讨论 2018-04-03 15:27:12
    首先 我遇到的问题是 接口调用时需要更新缓存 而更新缓存又是个说快不快的过程 所以打算做异步调用 返回我所需要的结果即可 ,至于缓存什么时候更新完 就不是我所需要关注的了废话不多说 上代码public class ...
  • SpringBoot异步调用方法

    千次阅读 2019-04-23 18:28:29
    SpringBoot异步调用方法 一、spring boot--使用异步请求,提高系统的吞吐量 https://blog.csdn.net/liuchuanhong1/article/details/78744138 1.使用Callable来实现 2. 通过WebAsyncTask,也能实现异步调用 ...
  • Dubbo异步调用实现

    千次阅读 2018-11-13 11:36:07
    1. 当使用异步调用时建议要和原有api进行区别,即将同步调用和异步调用的api接口分离 2.api注入时添加异步调用标示 3.在网关启动类开启异步调用 4.在网关为需要异步调用的接口添加异步调用代码 ...
  • 基于dubbo实现异步调用 增加consumer配置 这种方式很简单,只需要在服务引用时增加dubbo:method配置即可,如下所示,其中name为需要异步调用的方法名,async表示是否启用异步调用。 <dubbo:reference id=...
  • java线程异步调用

    千次阅读 2018-11-07 09:54:13
    系统登录的时候,需要根据用户ID生成一些和当前用户有关的数据放在缓存里,如果不考虑异步调用,则整个登录过程可能需要近8S的时间,这肯定是无法接受的。因而需要在登录的时候,将这些与登录无关的数据操作提取出来...
  • APM调用链追踪之跟踪异步调用

    千次阅读 2017-01-19 09:49:57
    跟踪异步调用所谓异步调用,是指创建任务和处理任务是在2个不同的线程上的调用。如果要跟踪异步调用,那么需要: 1.拦截创建异步任务的方法,并且赋予一个AsyncTraceId 2.把AsyncTraceId传给异步任务的处理方法 3...
  • Springboot异步调用 全解析

    千次阅读 2018-10-23 17:34:03
    本文主要介绍Springboot异步调用,包括: 1、Springboot同步调用演示; 2、Springboot两种异步调用方式; 3、Springboot使用注解的异步调用方式详解; 4、Springboot使用注解异步调用时的异常处理; 5、利用Future...
  • PHP异步调用

    千次阅读 2018-07-26 16:37:00
    PHP异步调用" date: 2016-08-04 00:02:32 +0800 comments: true categories: [php] popen+curl 实现PHP异步调用 从上次开始复习到起已经好久没有写过博客了,最近实习期间遇到了很多问题,想写点东西来做个...
  • Springboot实现方法异步调用

    千次阅读 2020-01-15 22:18:31
    文章目录SpringBoot中使用 async实现异步调用定义线程池使用实战单元测试注意事项Spring中用ThreadPoolTaskExecutor实现异步调用 SpringBoot中使用 async实现异步调用 基于注解的使用方式包括如下三步: 启动类...
  • dubbo异步调用变同步 当consumer或provider配置async属性时,会有传递性,后面调用都会变异步,如果链路上有一个地方代码是同步方式,那么这个地方会返回null 要么将所有链路上的代码改异步方式(Future),要么把...
  • 同步调用和异步调用

    万次阅读 2017-02-10 14:02:34
    我们知道,常见的方法...但是,如果我们面对是基于粗粒度的服务组件,面对的是一些需要比较长时间才 能有响应的应用场景,那么我们就需要一种非阻塞式调用方式,即异步调用方式。 SCA编程模式提供了三种方式的异步
  • LabVIEW调用子VI(subVI)有两种方法:1)通过程序框图-查看(菜单)-函数-选择VI...,在程序框图上添加子VI时,该子VI的调用方法是静态链接的,即编译生成可执行程序后,子VI的代码将会被静态链接到可...异步调用优...
  • SpringBoot使用@Async异步调用

    万次阅读 多人点赞 2018-06-22 09:25:50
    什么是“异步调用”?“异步调用”对应的是“同步调用”,同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行;异步调用指程序在顺序执行时,不等待异步调用的语句返回结果就...
  • Java接口异步调用

    千次阅读 2017-10-12 07:49:47
    java接口调用从调用方式上可以分为3类:同步调用,异步调用,回调;同步调用基本不用说了,它是一种阻塞式的调用,就是A方法中直接调用方法B,从上往下依次执行。今天来说说异步调用。 什么是异步调用? 我的理解...
  • Dubbo的异步调用

    千次阅读 2019-02-18 18:51:35
    1.背景 分布式服务架构 当垂直应用越来越多,应用...今天说一下的Dubbo的异步调用 2.基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小。 3.在 consum...
  • HSF异步调用

    千次阅读 2015-05-18 17:24:30
    1.引入 ... 但是有些是不需要一直等待服务端返回结果的,对于这些服务,hsf提供异步调用的方式,让客户端不必同步阻塞在hsf操作上 2.异步调用  (1)说明  异步调用在发起调用时,HSF
  • WPF 实现异步调用

    千次阅读 2015-10-21 13:46:49
    在WPF中,实现异步调用的代码如下: System.Windows.Threading.Dispatcher.Invoke( new Action(()=> { CallMethodName(); //要异步调用的方法或异步执行的语句 }), System.Windows.Threading....
  • spring的异步调用

    千次阅读 2017-11-04 14:04:24
    异步调用除了可以使用多线程以外,spring自已也实现了通过注解进行异步调用的功能,我们只需要进行一些简单的配置,并且在需要异步调用的方法上添加对应的注解即可。 在applicationContext.xml中添加如下:...
  • 异步调用四大方法

    千次阅读 2016-02-29 13:38:25
    C#异步调用四大方法是什么呢?C#异步调用四大方法的使用是如何进行的呢?让我们首先了解下什么时候用到C#异步调用: .NET Framework 允许您C#异步调用任何方法。定义与您需要调用的方法具有相同签名的委托;公共...
  • spring mvc 异步调用 @Async

    千次阅读 2018-08-03 10:35:01
    异步调用”对应的是“同步调用”,同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行;异步调用指程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的程序。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 692,419
精华内容 276,967
关键字:

异步调用