web-dev-qa-db-fra.com

Spring 3: Comment appeler des méthodes annotées @Async à partir de TaskExecutor

L'exécution de tâches asynchrones est nouvelle pour moi au printemps. Pardonnez-moi donc si cela ressemble à une question idiote.

J'ai lu que l'annotation @Async est introduite à partir de Spring 3.x au niveau de la méthode. L'appel de cette méthode se produira de manière asynchrone . J'ai également lu que nous pouvons configurer ThreadPoolTaskExecutor dans le fichier de configuration Spring.

Ce que je ne comprends pas, c’est que la procédure d’appel d’une méthode annotée @Async à partir d’un exécuteur tak laisse supposer - AsyncTaskExecutor

Auparavant, nous faisions quelque chose comme dans un cours:

@Autowired protected AsyncTaskExecutor executor;

Et alors

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

Je ne suis pas en mesure de comprendre la relation entre les méthodes annotées @Async et TaskExecutor.

J'ai essayé beaucoup de recherches sur Internet mais je ne pouvais rien obtenir à ce sujet.

Quelqu'un peut-il donner un exemple pour la même chose?.

11
tarares

Voici un exemple d'utilisation de @Async:

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

Appelez maintenant cette méthode depuis une autre classe et elle s'exécutera de manière asynchrone. Si vous voulez une valeur de retour, utilisez Future

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

La relation entre @Async et TaskExecutor est que @Async utilise une TaskExecutor dans les coulisses. De la docs:

Par défaut, lorsque vous spécifiez @Async sur une méthode, l'exécuteur qui sera utilisé est celui fourni à l'élément 'piloté par les annotations', comme décrit ci-dessus. Toutefois, l'attribut value de l'annotation @Async peut être utilisé lorsqu'il est nécessaire d'indiquer qu'un exécuteur autre que celui par défaut doit être utilisé lors de l'exécution d'une méthode donnée.

Donc, pour configurer un exécuteur par défaut, ajoutez ceci à votre configuration printanière.

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

Ou d'utiliser un exécuteur particulier pour un usage unique, essayez

@Async("otherExecutor")

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

30
Planky

Exemple complet

  1. Printemps config

    @Configuration        
    @EnableAsync        
    @ComponentScan("com.async")
    public class AppConfig {
    
        @Bean
        public AsyncManager asyncManger() {
            return new AsyncManager();
        }
    
        @Bean
        public AsyncExecutor asyncExecutor() {
            return new AsyncExecutor();
        }
    }
    
  2. Classe d'exécuteur créée, l'exécuteur que j'ai créé pour que spring prenne en charge la gestion des threads.

    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. Créez un manager.

    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. Configurez votre classe de service.

    @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. Modèle.

    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. Tester pour courir

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

Dans le fichier de configuration, il convient de mentionner une tâche avec annotation avec le nom du pool de threads et la méthode avec @Async (nom du pool) sera exécutée dans le cadre de ce pool. Cela crée une classe proxy pour celle qui possède l'annotation @Async et l'exécute pour chaque thread.

1
user3631644

Vous pouvez ajouter @Async sur votre méthode et les éléments suivants dans votre contexte d'application.

    <task:annotation-driven executor="asynExecutor"/>   
    <task:executor id="asynExecutor" pool-size="5" />
0
Lijo Monkuzhy