• java异步调用的4种实现(转)


    转自:https://www.jb51.net/article/240466.htm

    参考:https://www.liaoxuefeng.com/wiki/1252599548343744/1306581182447650

    一.利用多线程

    直接new线程

    Thread t = new Thread(){
      @Override
      public void run() {
        longTimeMethod();
      }
    };

    使用线程池

    private ExecutorService executor = Executors.newCachedThreadPool() ;
     
        public void fun() throws Exception {
     
            executor.submit(new Runnable(){
     
                @override
     
                    public void run() {
     
                        try {
                         //要执行的业务代码,我们这里没有写方法,可以让线程休息几秒进行测试
     
                            Thread.sleep(10000);
     
                            System.out.print("睡够啦~");
     
                        }catch(Exception e) {
     
                            throw new RuntimeException("报错啦!!");
     
                        }
     
                    }
     
            });
     
        }

    二.采用Spring 的异步方法去执行(无返回值)

    在启动类或者配置类加上 @EnableAsync 注解.

    package me.deweixu.aysncdemo;
     
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableAsync;
     
    @EnableAsync
    @SpringBootApplication
    public class AysncDemoApplication {
     
     public static void main(String[] args) {
      SpringApplication.run(AysncDemoApplication.class, args);
     }
    }
     

    先把longTimeMethod 封装到Spring的异步方法中,这个方法一定要写在Spring管理的类中,注意注解@Async

     

    @Async注解可以用在方法上,也可以用在类上,用在类上,对类里面所有方法起作用

    @Service
    public class AsynchronousService{
      @Async
      public void springAsynchronousMethod(){
        longTimeMethod();
      }
    }

    其他类调用这个方法。这里注意,一定要其他的类,如果在同类中调用,是不生效的。具体原因,可以去学习一下Spring AOP的原理

     
    @Autowired
    private AsynchronousService asynchronousService;
     
    public void useAsynchronousMethod(){
      //我们需要执行的代码1
      asynchronousService.springAsynchronousMethod();
     //我们需要执行的代码2
    }

    三.采用Spring 的异步方法+Future接收返回值

    先把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);
    }

    四.原生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获得异步执行结果时,要么调用阻塞方法get(),要么轮询看isDone()是否为true,这两种方法都不是很好,因为主线程也会被迫等待。

    五.原生CompletableFuture方法

    CompletableFuture提供了几个回调点,可以在对应点上传入方法,可以在任务成功或失败的时候得到通知,是比较优雅的异步非阻塞获取响应的方式
    @Slf4j
    public class Test {
        
        public static void main(String[] args) throws InterruptedException {
            Test test = new Test();
            CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(test::addTable);
            //任务成功会调用这个方法
            completableFuture.thenAccept((s)->{
                log.info("任务完成!拿到结果了:" + s);
            });
            //任务失败会调用这个方法
            completableFuture.exceptionally((e)->{
                log.info("出现异常,任务失败了:" + e);
                return null;
            });
            // 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
            Thread.sleep(2000);
        }
    
         String addTable() {
            try {
                Thread.sleep(1000);
                 int i=1/0;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("执行 addTable");
            return "addTable";
        }
        
    }
  • 相关阅读:
    Jmeter系列(64)- JMeter JSR223 入门
    Jmeter系列(63)- Beanshell 入门
    Jmeter系列(62)- 详解 JSON 断言
    Jmeter系列(61)- 详解断言持续时间
    Jmeter系列(60)- 详解响应断言
    取球游戏|2012年蓝桥杯B组题解析第十题-fishers
    夺冠概率|2012年蓝桥杯B组题解析第九题-fishers
    密码发生器|2012年蓝桥杯B组题解析第八题-fishers
    放棋子|2012年蓝桥杯B组题解析第七题-fishers
    大数乘法|2012年蓝桥杯B组题解析第六题-fishers
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/16480318.html
Copyright © 2020-2023  润新知