【问题标题】:@async in spring behaviour is synchronousspring 行为中的@async 是同步的
【发布时间】:2017-08-15 14:26:56
【问题描述】:

我编写了一段代码来检查 Spring 框架中的 @Async 注释行为。

@RequestMapping( value="/async" , method = RequestMethod.GET)
  public ModelAndView AsyncCall(HttpServletRequest request)
  {
        async1();
        async2();
    return new ModelAndView("firstpage");
  }

  @Async
  private void async1(){
      System.out.println("Thread 1 enter");
      try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
      System.out.println("Thread 1 exit");
  }

  @Async
  private void async2(){
      System.out.println("Thread 2 enter");
      try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
      System.out.println("Thread 2 exit");
  }

这段代码的输出如下。

Thread 1 enter
Thread 1 exit
Thread 2 enter 
Thread 2 exit

通过查看此输出,这两个@Async 函数调用本身似乎是同步的。

据我所知,这两个是不同的线程,应该自己异步运行。

根据正在打印的spring代理调用日志更改代码后的样子。

主线程名称:http-apr-8080-exec-8

Thread 1 enter
Async-1 Thread Name: neutrinoThreadPoolExecutor-1
Thread 1 exit
Thread 2 enter
Async-2 Thread Name: neutrinoThreadPoolExecutor-1
Thread 2 exit

两个异步调用的线程名称相同,但似乎仍然没有呈现异步行为。

【问题讨论】:

  • 代理建议不适用于自调用...
  • 我已经用 spring 代理建议更改了代码。

标签: java spring spring-mvc asynchronous


【解决方案1】:

这些是@Async 不适合我的情况

  1. @EnableAsync 不见了
  2. @Async 方法未公开
  3. @Async 注释的方法是从同一类的另一个方法调用的。可能会绕过异步代理代码,只调用普通方法。

【讨论】:

    【解决方案2】:

    Spring 的@Async 注解有两条规则需要你遵守。

    1. 只能应用于public 方法
    2. 自调用 - 从同一类中调用异步方法 - 不起作用

    原因很简单——该方法需要公开,以便它可以被代理。 而自调用也不起作用,因为它绕过了代理,直接调用了底层方法。

    【讨论】:

    • 方法可以是包私有的
    【解决方案3】:

    您是否在 Spring 应用程序中启用了异步?在 Spring Boot 中,您可以执行类似的操作。

    @SpringBootApplication
    @EnableAsync
    public class Application extends AsyncConfigurerSupport {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
        @Override
        public Executor getAsyncExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(2);
            executor.setMaxPoolSize(2);
            executor.setQueueCapacity(500);
            executor.setThreadNamePrefix("GithubLookup-");
            executor.initialize();
            return executor;
        }
    
    }
    

    @EnableAsync 注解开启了 Spring 在后台线程池中运行 @Async 方法的能力。

    【讨论】:

    • 是否有任何选项可以通过 web.xml 启用它。 ?
    【解决方案4】:

    您必须从当前类之外调用方法。否则 spring 魔法 不会被执行。

    所以试试这样的:

    @Inject
    MyAsyncService asyncService;
    
    @RequestMapping( value="/async" , method = RequestMethod.GET)
    public ModelAndView AsyncCall(HttpServletRequest request) {
        asyncService.async1();
        return new ModelAndView("firstpage");
    }
    

    MyAsyncService

    @Component
    public MyAsyncService {
        @Async
        public void async1() {
             //code
        } 
    }
    

    【讨论】:

      【解决方案5】:

      添加启用异步的配置。

      @Configuration
      @EnableAsync
      public class AsyncWorkerConfig {
      
          @Bean(name = "abcExecutors")
          public ExecutorService ch3Executors() {
              int corePoolSize = 6;
              int maxPoolSize = 6;
              int keepAliveTime = 100000;
      
              return new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.MILLISECONDS,
                      new LinkedBlockingQueue<Runnable>(),
                      new ThreadFactoryBuilder()
                              .setDaemon(false)
                              .setNameFormat("abc-parser-t-%d").build());
          }
      
      }
      

      创建类并将异步添加到方法中。

       @Service
      public class AsyncFileProcessor {
      
          @Async("abcExecutors")
          public void process(final String filePath){
            //your code logic
        }
      
      }
      
      

      【讨论】:

        猜你喜欢
        • 2018-06-24
        • 2015-12-10
        • 1970-01-01
        • 1970-01-01
        • 2017-05-02
        • 1970-01-01
        • 1970-01-01
        • 2019-05-20
        • 2017-09-13
        相关资源
        最近更新 更多