13

我是 Spring 中异步任务执行的新手,所以如果这听起来像一个愚蠢的问题,请原谅我。

我读到 @Async 注释是从 Spring 3.x 开始在方法级别引入的,该方法的调用将异步发生。我还读到我们可以在 spring 配置文件中配置 ThreadPoolTask​​Executor。

我无法理解的是,假设如何从 tak 执行器调用 @Async 带注释的方法 - AsyncTaskExecutor

之前我们曾经在课堂上做类似的事情:

@Autowired protected AsyncTaskExecutor executor;

接着

executor.submit(<Some Runnable or Callable task>)

我无法理解 @Async 注释方法和 TaskExecutor 之间的关系。

我尝试在互联网上进行了很多搜索,但对此一无所获。

有人可以提供一个相同的例子。

4

4 回答 4

30

这是一个@Async使用示例:

@Async
void doSomething() {
    // this will be executed asynchronously
}

现在从另一个类调用该方法,它将异步运行。如果您想要返回值,请使用Future

@Async
Future<String> returnSomething(int i) {
    // this will be executed asynchronously
}

@Async和之间的关系TaskExecutor@Async使用了一个TaskExecutor幕后。从文档:

默认情况下,在方法上指定 @Async 时,将使用的执行程序是提供给上述“注释驱动”元素的执行程序。但是,当需要指示在执行给定方法时应使用默认值以外的执行器时,可以使用 @Async 注释的 value 属性。

因此,要设置默认执行程序,请将其添加到您的 spring 配置中

<task:annotation-driven executor="myExecutor" />

或者使用特定的执行器进行单次使用尝试

@Async("otherExecutor")

http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/scheduling.html#scheduling-annotation-support-async

于 2013-10-02T18:39:15.517 回答
5

完整示例

  1. 配置弹簧

    @Configuration        
    @EnableAsync        
    @ComponentScan("com.async")
    public class AppConfig {
    
        @Bean
        public AsyncManager asyncManger() {
            return new AsyncManager();
        }
    
        @Bean
        public AsyncExecutor asyncExecutor() {
            return new AsyncExecutor();
        }
    }
    
  2. 创建了执行器类,我创建了执行器,以便 spring 负责线程管理。

    public class AsyncExecutor extends AsyncConfigurerSupport {
    
        @Override
        public Executor getAsyncExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(2);
            executor.setMaxPoolSize(2);
            executor.setQueueCapacity(500);
            executor.setThreadNamePrefix("Violation-");
            executor.initialize();
            return executor;
        }
    }
    
  3. 创建经理。

    public class AsyncManager {
    
        @Autowired
        private AsyncService asyncService;
    
        public void doAsyncTask(){
            try {
                Map<Long, ViolationDetails> violation = asyncService.getViolation();
                if(!org.springframework.util.CollectionUtils.isEmpty(violation)){
                    violation.entrySet().forEach( violationEntry -> {System.out.println(violationEntry.getKey() +"" +violationEntry.getValue());});
                }
                System.out.println("do some async task");
            } catch (Exception e) {
            }
    
        }
    }
    
  4. 配置您的服务类。

    @Service
    public class AsyncService {
    
        @Autowired
        private AsyncExecutor asyncExecutor;
    
        @Async
        public Map<Long,ViolationDetails> getViolation() {
            // TODO Auto-generated method stub
            List<Long> list = Arrays.asList(100l,200l,300l,400l,500l,600l,700l);
            Executor executor = asyncExecutor.getAsyncExecutor();
            Map<Long,ViolationDetails>  returnMap = new HashMap<>();
            for(Long estCode : list){
                ViolationDetails violationDetails = new ViolationDetails(estCode);
                returnMap.put(estCode, violationDetails);
                executor.execute((Runnable)new ViolationWorker(violationDetails));
            }
            return returnMap;       
        }
    }
    class ViolationWorker implements Runnable{
    
        private ViolationDetails violationDetails;
    
        public ViolationWorker(ViolationDetails violationDetails){
            this.violationDetails = violationDetails;
        }
    
        @Override
        public void run() {
            violationDetails.setViolation(System.currentTimeMillis());
            System.out.println(violationDetails.getEstablishmentID() + "    " + violationDetails.getViolation());
        }
    }
    
  5. 模型。

    public class ViolationDetails {
        private long establishmentID;
        private long violation;
    
    
        public ViolationDetails(long establishmentID){
            this.establishmentID = establishmentID;
        }
    
        public long getEstablishmentID() {
            return establishmentID;
        }
        public void setEstablishmentID(long establishmentID) {
            this.establishmentID = establishmentID;
        }
        public long getViolation() {
            return violation;
        }
        public void setViolation(long violation) {
            this.violation = violation;
        }
    
    }
    
  6. 测试运行

    public class AppTest {
        public static void main(String[] args) throws SQLException {
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
            ctx.register(AppConfig.class);
            ctx.refresh();
    
            AsyncManager task= ctx.getBean(AsyncManager.class);
            task.doAsyncTask();
        }
    }
    
于 2017-05-19T10:34:19.267 回答
1

在配置文件中,应该提到一个带有线程池名称的注释驱动任务和带有@Async(池名称)的方法将作为该池的一部分执行。这将为具有 @Async 注释的代理类创建一个代理类,并为每个线程执行它。

于 2014-05-14T04:43:00.937 回答
0

您可以在您的方法上添加@Async,并将以下内容添加到您的应用程序上下文中。

    <task:annotation-driven executor="asynExecutor"/>   
    <task:executor id="asynExecutor" pool-size="5" />
于 2015-04-27T22:34:02.067 回答