Spring 4异步无法正常工作

时间:2015-08-20 15:32:15

标签: spring asynchronous

我正在使用Spring 4 Web应用程序,并且遇到同步运行的@Async问题。这是100%注释驱动。没有XML文件。

应用:

package com.kc2112.app;

import com.kc2112.app.controllers.MyStopWatch;
import javax.annotation.Resource;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

@EnableAsync
@EnableScheduling
@Configuration
public class WebApp extends AbstractAnnotationConfigDispatcherServletInitializer implements AsyncConfigurer {

    @Resource
    @Qualifier("stopwatch")
    public MyStopWatch stopwatch;

    public WebApp() {
        super();
        stopwatch = new MyStopWatch();
    }

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[0];
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{AppConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    public TaskExecutor getAsyncExecutor() {
        ThreadPoolTaskExecutor te = new ThreadPoolTaskExecutor();
        te.setMaxPoolSize(25);
        te.setThreadNamePrefix("LULExecutor-");
        te.initialize();
        return te;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }

}

配置:

    package com.kc2112.app;

import com.kc2112.app.controllers.MySampleService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;

import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;

@Configuration
@EnableAsync
@ComponentScan( basePackages = {"com"}, excludeFilters={
  @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=MySampleService.class)} )
public class AppConfig{

   @Bean
   public static PropertySourcesPlaceholderConfigurer properties() {
      return new PropertySourcesPlaceholderConfigurer();
   }

   @Bean
    public UrlBasedViewResolver urlBasedViewResolver()
    {
        UrlBasedViewResolver res = new InternalResourceViewResolver();
        res.setViewClass(JstlView.class);
        res.setPrefix("/WEB-INF/jsp/");
        res.setSuffix(".jsp");

        return res;
    }
}

控制器:

    package com.kc2112.app.controllers;

import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyAsyncController {

    @Autowired
    MyStopWatch stopwatch;

    public MySampleService mySampleService = new MySampleService();

    @RequestMapping(value = "/go", produces = {MediaType.TEXT_HTML_VALUE}, method = RequestMethod.GET)
    public String taskExecutor() throws InterruptedException, ExecutionException {

        ArrayList<Future<Boolean>> asyncResults = new ArrayList();


        for (int i = 0; i < 10; i++) {
            asyncResults.add(mySampleService.callAsync(i));
        }
        return "time passed is " + stopwatch.getTime();
    }

}


Component:

    package com.kc2112.app.controllers;

import java.util.concurrent.Future;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;


@Component
public class MySampleService {

    @Async
    public Future<Boolean> callAsync(int taskCall) throws InterruptedException {

        System.out.println("starting thread" + taskCall);

        for (int i = 0; i < 10; i++) {
            System.out.println("thread " + taskCall + " count is " + i);
        }

        return new AsyncResult<Boolean>(true);
    }

}


Stopwatch:

    package com.kc2112.app.controllers;

import org.apache.commons.lang.time.StopWatch;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Component
@Service
@Qualifier("stopwatch")
public class MyStopWatch extends StopWatch {

    public MyStopWatch(){
        super();
        this.start();
    }
}

我尝试了很多东西,但它总是打印显然不是异步的结果。

2 个答案:

答案 0 :(得分:0)

public MySampleService mySampleService = new MySampleService();

这是你烦恼的原因。您必须将MySampleService自动装入控制器,而不是自己创建实例。这是Spring将组件包装到异步代理中的唯一方法,该异步代理将检测注释,拦截方法调用,创建任务并将其提交给执行者。

答案 1 :(得分:0)

YES !!!!阅读完这篇文章后:

Spring ThreadPoolTaskExecutor only running one thread

我对我的app类进行了一些更改。关键问题似乎是设置核心池大小。这是修复问题的行的类......

以下是关于它的春季文档:

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html#setCorePoolSize-int-

package com.kc2112.app;

import com.kc2112.app.controllers.MyStopWatch;
import javax.annotation.Resource;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

@EnableAsync
@EnableScheduling
@Configuration
public class WebApp extends AbstractAnnotationConfigDispatcherServletInitializer implements AsyncConfigurer {

    @Resource
    @Qualifier("stopwatch")
    public MyStopWatch stopwatch;

    public WebApp() {
        super();
        stopwatch = new MyStopWatch();
    }

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[0];
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{AppConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    public TaskExecutor getAsyncExecutor() {
        ThreadPoolTaskExecutor te = new ThreadPoolTaskExecutor();
        te.setMaxPoolSize(25);
        te.setThreadNamePrefix("LULExecutor-");
        te.setCorePoolSize(25);    //This was the critical line...
        te.initialize();
        return te;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }

}