Run program in background in Spring

There may be situation where you may want to run your application in background.
For example, assume there are four logic/processes in your application and you want
three processes to run in background. In this case these three processes running in
background would reduce user waiting time.


Program Explanation: 
There are 2 classes in this example. 
 1) MainMethod.java 
 2) AsyncTest.java 
 3) ThreadConfig.java MainMethod class calls AsyncTest class. 
 The code which is to be executed in background is placed in AsyncTest.java class.   ThreadConfig.java is used to enable Spring’s asynchronous method execution capability.

MainMethod.java


import java.sql.SQLException;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainMethod {
 public static void main(String[] args) throws SQLException {
  AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
  ctx.register(ThreadConfig.class);
  ctx.refresh();
  AsyncTest task= ctx.getBean(AsyncTest.class);
  System.out.println("main start"); 
  task.runFromAnotherThreadPool();
  System.out.println("main end"); 
 }
}


AsyncTest.java


import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

public class AsyncTest {  
 
 @Async("specificTaskExecutor")
 public void runFromAnotherThreadPool() 
 { 
  System.out.println("You function code here 1");
  
  ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  System.out.println("executor.getActiveCount(): "+executor.getActiveCount());
  System.out.println("executor.getPoolSize(): "+executor.getPoolSize());
  System.out.println("executor.getThreadNamePrefix(): "+executor.getThreadNamePrefix());
  System.out.println("executor.getMaxPoolSize(): "+executor.getMaxPoolSize());
  
  
     try 
     {
   Thread.sleep(15 * 100);
   System.out.println("try block");
   
  } catch (InterruptedException e) 
     {   
   e.printStackTrace();
  }
     System.out.println("You function code here 2");     
 }
}



ThreadConfig.java


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class ThreadConfig 
{
    @Bean(name = "specificTaskExecutor")
    public TaskExecutor specificTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(500);
        executor.setQueueCapacity(20);
executor.setThreadNamePrefix("xyz"); executor.initialize(); return executor; } @Bean public AsyncTest asyncTask() { return new AsyncTest(); } }


Output:
main start
main end
You function code here 1
executor.getActiveCount(): 0
executor.getPoolSize(): 1
executor.getThreadNamePrefix(): ThreadPoolTaskExecutor-
executor.getMaxPoolSize(): 2147483647
try block
You function code here 2

Note:
Adding only @Async over a method will not work.
We need to enable Spring’s asynchronous method execution capability by using
@EnableAsync annotation in one of our configuration classes.

setCorePoolSize() vs setMaxPoolSize() vs setQueueCapacity()
Take this example. Starting thread pool size is 1, core pool size is 5, max pool size is 10 and the queue is 100.
If the number of threads is less than the corePoolSize, create a new Thread to run a new task.
If the number of threads is equal (or greater than) the corePoolSize, put the task into the queue.
If the queue is full, and the number of threads is less than the maxPoolSize, create a new thread to run tasks in.
If the queue is full, and the number of threads is greater than or equal to maxPoolSize, reject the task.

Rules for @Async 
 1) It must be applied to public methods only 
 2) Self-invocation – calling the async method from within the same class – won’t work The reasons are simple – the method needs to be public so that it can be proxied and
self-invocation doesn’t work because it bypasses the proxy and calls the underlying method
directly.

No comments:

Post a Comment