@async在spring中的行为是同步的

时间:2017-03-23 06:55:43

标签: java spring spring-mvc asynchronous

我编写了一段代码来检查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函数调用本身是同步的。

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

根据弹出的代理调用日志更改代码后打印就像。

主线程名称: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

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

4 个答案:

答案 0 :(得分:5)

@Async对我不起作用的情况

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

答案 1 :(得分:1)

您是否在Spring Application中启用了Async?在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方法的能力。

答案 2 :(得分:1)

您必须从当前班级以外的地方调用这些方法。否则 spring magic 将无法执行。

所以尝试这样的事情:

@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
    } 
}

答案 3 :(得分:1)

Spring @Async注释有两条规则需要遵循。

  1. 必须仅适用于public种方法
  2. 自我调用 - 从同一个类中调用异步方法 - 将无法正常工作
  3. 原因很简单 - 该方法需要公开才能被代理。 并且自我调用不起作用,因为它绕过代理并直接调用底层方法。