Spring 3: How to call @Async annotated methods from the TaskExecutor Spring 3: How to call @Async annotated methods from the TaskExecutor multithreading multithreading

Spring 3: How to call @Async annotated methods from the TaskExecutor


Here's an example of @Async use:

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

Now call that method from another class and it will run asynchronously. If you want a return value use a Future

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

The relationship between @Async and TaskExecutor is that @Async uses a TaskExecutor behind the scenes. From the docs:

By default when specifying @Async on a method, the executor that will be used is the one supplied to the 'annotation-driven' element as described above. However, the value attribute of the @Async annotation can be used when needing to indicate that an executor other than the default should be used when executing a given method.

So to set up a default executor, add this to your spring config

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

Or to use a particular executor for a single use try

@Async("otherExecutor")

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


Complete Example

  1. Config Spring

    @Configuration        @EnableAsync        @ComponentScan("com.async")public class AppConfig {    @Bean    public AsyncManager asyncManger() {        return new AsyncManager();    }    @Bean    public AsyncExecutor asyncExecutor() {        return new AsyncExecutor();    }}
  2. Executor Class Created, Executor i have created so that spring takes care of thread management.

    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. Create a 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. Configure your service class.

    @Servicepublic 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. Model.

    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. Test to Run

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


In the config file, one should mention an annotation driven task with the thread pool name and method with @Async(pool name) will be executed as part of that pool. This creates a proxy class for the one which has @Async annotation and executes it for every thread.