1
private final ExecutorService pool = Executors.newFixedThreadPool(5);

for (ProductInfo prod : product) {
                pool.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            prod.checkout(processList);
                        } catch (InterruptedException e) {
                            log.error("PRODUCT INFO EXCEPTION", e);
                        }
                    }
                });
            }

All calls to prod.checkout method call different apis having no correlation between them.

ProductInfo.java

@Async
    public void checkout(List<ProcessLog> list) throws InterruptedException {
        process = processUtil.start(getHome(), job);
        list.add(process);
        preprocess();
        execute();
        postprocess();
        list.remove(process);
        processUtil.end(process);
    }

At any time i see only two threads running, what can i do to make 5 threads running at any time?

azurefrog
  • 10,785
  • 7
  • 42
  • 56
Abhishek Agarwal
  • 846
  • 4
  • 13
  • 34
  • You mix up two approaches: @ Async (if called on a properly @ Injected object) will execute asynchronously anyways, so adding an ExecutorService might buy you nothing except queueing calls to checkout to be started from different threads. – Jan Dec 06 '15 at 10:45
  • @Jan: Initially i was calling checkout directly (without executor) than also i was seeing only 2 threads working at a time. – Abhishek Agarwal Dec 06 '15 at 11:16
  • @AbhishekAgarwal Try removing the annotation Async and put Thread.sleep(5000l); within checkout code so as to make it run atleast for few seconds. If needed put this statement System.out.println(Thread.currentThread().getId()); to know the number of active theads – prem kumar Dec 06 '15 at 11:52

2 Answers2

1

Use TWO beans.

@Service   
public class CheckoutService {

    @Async
    public void checkout(List<ProcessLog> list) throws InterruptedException {
        process = processUtil.start(getHome(), job);
        list.add(process);
        preprocess();
        execute();
        postprocess();
        list.remove(process);
        processUtil.end(process);
    }
}

The second bean invoke the first one, so Spring can handle @Aync (see this answer for more details about the reason for splitting: https://stackoverflow.com/a/22561903/280244)

@Service   
public class CheckoutAsyncInvoker {

    @Autowired
    CheckoutService  checkoutService 

    public void runner()
        for (ProductInfo prod : product) {
            processList=...
            this.checkoutService.checkout(processList);
        }
    }
}

Configuration:

 @Configuration
 @EnableAsync
 public class AppConfig implements AsyncConfigurer {

     @Override
     public Executor getAsyncExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.setCorePoolSize(5);
         executor.setMaxPoolSize(5);
         executor.setQueueCapacity(11);
         executor.setThreadNamePrefix("MyExecutor-");
         executor.initialize();
         return executor;
     }
 }
Community
  • 1
  • 1
Ralph
  • 118,862
  • 56
  • 287
  • 383
0

May be it is because there is @Async annotation on checkout() method. As soon as checkout() method is called execution in run() method mentioned here is completed and code within checkout() is running in a altogether different thread different from this thread pool.

If you remove this annotation and ensure the method executes for quite some time then you can see that all 5 threads getting used up.

prem kumar
  • 5,641
  • 3
  • 24
  • 36