2015-08-20 180 views
1

我正在處理Spring 4 Web應用程序,並且遇到了同步運行的@Async問題。這是100%註釋驅動。沒有XML文件。春季4異步不起作用

應用:

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(); 
    } 
} 

我試過千頭萬緒,但它總是打印結果這顯然不是異步。

回答

0
public MySampleService mySampleService = new MySampleService(); 

這是你的煩惱的原因。您必須將MySampleService自動裝入控制器,而不是自己創建實例。這是Spring將組件封裝到異步代理中的唯一方法,該異步代理將檢測註釋,攔截方法調用,創建任務並將其提交給執行程序。

0

是的!通過閱讀這篇文章後:

Spring ThreadPoolTaskExecutor only running one thread

我做我的應用程序類中的一些變化。關鍵問題似乎是設置核心池大小。下面是與固定的問題就行了...類

下面是關於它的春天文檔:

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

}