Spring ThreadPoolTaskExecutor with Callable interface for concurrency programming

Callable is a Java interface that is an useful methodology for control multi-threading returns on concurrency development.

The tutorial will guide you to build a concurrency program with ThreadPoolTaskExecutor of Spring Framework and Callable interface.

I. Technology

– Java 8
– Maven 3.3.9
– Editor: Spring Tool Suite – Version 3.7.3.RELEASE

II. Overview of Spring multi-thread with Callable project

– Program has 5 threads, that works concurrently. At parent thread, for managing the returns of all child threads, We use Callable interface.

1. Structure of project

spring thread pool callable structure

2. Step to do

– Create Spring Boot project.
– Setup ThreadPoolTaskExecutor.
– Create CallableWorker that implements Callable interface.
– Create a Simple Web Controller

III. Practice
1. Create Spring Boot project

Open Spring Tool Suite, choose File->New->Spring Starter Project, input project information as below picture:
spring-callable-project-info

Press Next button, then add needed dependencies:
– For Web MVC dependency, choose Web then select Web as below:

spring-callable-web-mvc-dependency

Press Finish then Spring Boot Project will be created.

Check pom.xml dependency:


    org.springframework.boot
    spring-boot-starter-web

2. Setup ThreadPoolTaskExecutor

– Configure application.properties:

threadpool.corepoolsize=5
threadpool.maxpoolsize=10

– Configure a Spring ThreadPool:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 
@Configuration
public class ThreadPoolConfiguration {
     
    @Value("${threadpool.corepoolsize}")
    int corePoolSize;
     
    @Value("${threadpool.maxpoolsize}")
    int maxPoolSize;
     
    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
        pool.setCorePoolSize(corePoolSize);
        pool.setMaxPoolSize(maxPoolSize);
        pool.setWaitForTasksToCompleteOnShutdown(true);
        return pool;
    }
}
3. Create Callable Worker
import java.util.concurrent.Callable;
 
public class CallableWorker implements Callable{
 
    String name;
     
    public CallableWorker(String name) {
        this.name = name;
    }
     
    @Override
    public String call() throws Exception {
        process();
        String message = String.format("CallableWorker name: %s is Done", name);
        return message;
    }
     
    private void process(){ 
        for(int taskId=0; taskId < 10; taskId++){
            String message = String.format("CallableWorker name: %s is processing a taskId: %d", name, taskId);
            System.out.println(message);
        }
    }
     
}
4. Create a Simple Web Controller
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import com.springjava4dev.concurrency.callabletask.CallableWorker;
 
@RestController
public class WebController {
 
    @Autowired
    ThreadPoolTaskExecutor threadPool;
     
    @RequestMapping("/process")
    public String process(){
         
        String msg = "";
        List> futureList = new ArrayList<>();
        for(int threadNumber = 0; threadNumber < 5; threadNumber ++){
            CallableWorker callableTask = new CallableWorker(String.valueOf(threadNumber));
            Future result = threadPool.submit(callableTask);
            futureList.add(result);
        }
         
        for(Future future: futureList){
            try {
                msg += future.get() + "#####";
            } catch (Exception e){}
        }
         
        return msg;
    }
}
IV. Run Project

– Build Spring Boot project
Set Goals: clean install

– Run Project:
spring-boot-multi-thread-with-callable-interface-result

– Logs

...
CallableWorker name: 4 is processing a taskId: 0
CallableWorker name: 2 is processing a taskId: 2
CallableWorker name: 4 is processing a taskId: 1
CallableWorker name: 2 is processing a taskId: 3
CallableWorker name: 4 is processing a taskId: 2
CallableWorker name: 2 is processing a taskId: 4
CallableWorker name: 4 is processing a taskId: 3
CallableWorker name: 2 is processing a taskId: 5
CallableWorker name: 4 is processing a taskId: 4
CallableWorker name: 2 is processing a taskId: 6
CallableWorker name: 4 is processing a taskId: 5
CallableWorker name: 2 is processing a taskId: 7
CallableWorker name: 4 is processing a taskId: 6
CallableWorker name: 2 is processing a taskId: 8
CallableWorker name: 4 is processing a taskId: 7
CallableWorker name: 2 is processing a taskId: 9
CallableWorker name: 4 is processing a taskId: 8
CallableWorker name: 4 is processing a taskId: 9
CallableWorker name: 1 is processing a taskId: 0
...
V. Source Code

springboot-threadpool-callable



By grokonez | October 30, 2016.

Last updated on June 4, 2017.



Related Posts


2 thoughts on “Spring ThreadPoolTaskExecutor with Callable interface for concurrency programming”

  1. In above example if I move private void process() to another Bean (ThreadPoolThreadtask) and I wanted to call this method from there, below implementation is giving me issue (Null Pointer exception) as bean is not getting initialized. Can you please help.

    package com.test;
    
    import org.springframework.context.annotation.Bean;
    
    public class ThreadPoolThreadTask {
    	
    	@Bean
    	public void process(String name) {
    		for (int taskId = 0; taskId < 10; taskId++) {
    			String message = String.format(
    					"CallableWorker name: %s is processing a taskId: %d", name,
    					taskId);
    			System.out.println(message);
    		}
    	}
    
    
    }
    
    @Component
    @Scope("prototype")
    public class CallableWorker implements Callable {
    	
    	@Autowired
    	ThreadPoolThreadTask threadPoolThreadtask;
    
    	String name;
    
    	public CallableWorker(String name) {
    		this.name = name;
    	}
    
    	@Override
    	public String call() throws Exception {
    		
    		String message = null;
    		
    		try {
    			threadPoolThreadtask.process(name);
    //			process();
    			message = String.format("CallableWorker name: %s is Done", name);
    		} catch (Exception ex) {
    			ex.printStackTrace();
    			throw new Exception();
    		}
    		return message;
    	}
    

Got Something To Say:

Your email address will not be published. Required fields are marked *

*