Returning Data from Java Threads

There are a couple of ways in which threads can be created. i.e. Implementing Runnable Interface and extending Thread Class (Example here). Further we need to implement run method and do our processing inside the run method. This would look like below.

package com.bharatonjava.threads;

public class DoSomeTask implements Runnable {
		
	public static void main(String[] args) {

		Thread thread = new Thread(new DoSomeTask());
		thread.start();
	}
	
	/**
	 * Implement this method defined by Runnable Interface
	 */
	public void run() {
	
		System.out.println("your business logic goes in here.");
	}
}

One thing to note about above snippet is the return type of run() method. It is void. Means our thread can not return any value. What if your thread does some processing and you want to capture that output?

Java’s Concurrency API provides and elegant way to do this. Let us see this with the help of a simple example.

In our example we want to spawn a few threads to get Employee data from a DAO class and capture the data returned by those threads. Further you might want to send this collected data to your client as a response to his request. but this is not a part of our example in favor of simplicity.

1. Example Project Structure

returning-threads

2. Employee Domain Object

package com.bharatonjava.domain;

public class Employee implements Comparable<Employee>{

	private int id;
	private String name;
	private String location;
	
	public Employee() {
	}

	public Employee(int id, String name, String location) {
		super();
		this.id = id;
		this.name = name;
		this.location = location;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", location="
				+ location + "]";
	}

	public int compareTo(Employee o) {
		if(this.getId() < o.getId())
		{
			return -1;
		}else if(this.getId() > o.getId())
		{
			return 1;
		}
		return 0;
	}
	
}

3. DAO Class

EmployeeDao.java is a simple class that does not speak to database but for simplicity creates a collection of Employee Objects and returns one when requested based on employee id.

package com.bharatonjava.dao;

import java.util.HashMap;
import java.util.Map;

import com.bharatonjava.domain.Employee;

public class EmployeeDao {

	private static Map<Integer, Employee> emps;

	static {
		emps = new HashMap<Integer, Employee>();
		
		emps.put(1001, new Employee(1001, "Bharat", "Mumbai"));
		emps.put(1002, new Employee(1002, "Jayant", "Pune"));
		emps.put(1003, new Employee(1003, "Ravi", "Banglore"));
		emps.put(1004, new Employee(1004, "Kapil", "Delhi"));
		emps.put(1005, new Employee(1005, "Gaurav", "Pune"));		
	}

	public static Employee getEmployeeById(int empId) {
		return emps.get(empId);
	}
}

4. Task to be Done

TaskAsCallable.java should contain the task that we want our thread to do. Like in our case we just want to get an Employee instance form DAO using the employee id, but in real world this thread will do much more than this.

package com.bharatonjava.threads;

import java.util.concurrent.Callable;

import com.bharatonjava.dao.EmployeeDao;
import com.bharatonjava.domain.Employee;


public class TaskAsCallable implements Callable<Employee>{

	private int empId;
	
	public TaskAsCallable(int empId) {
		this.empId = empId;
	}
	
	public Employee call() throws Exception {
		
		/* this is where your business logic goes */
		return EmployeeDao.getEmployeeById(this.empId);
	}
}

Please note that our class implements Callable interface. This interface has one method named call(). We need to implement this method with the task that we want our thread to perform.

5. Main Class

In our main Class we create a thread pool of 5 threads using Executors.newFixedThreadPool(5) and then create a collection of Callable tasks.

We receive responses of each thread in the form of a Future object instance. Now to our executor we pass our collection of callables and by calling executorService.invokeAll(lst); method. This method blocks till all the threads complete their execution either gracefully or by throwing an awful Exception. The response of invokeAll() method is collected in a collection of Future instances.

Now we can iterate over this collection to get responses from each thread.

package com.bharatonjava.threads;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import com.bharatonjava.domain.Employee;

public class MainClass {

	public static void main(String[] args) throws InterruptedException, ExecutionException {

		ExecutorService executorService = Executors.newFixedThreadPool(5);
		
		List<Callable<Employee>> lst = new ArrayList<Callable<Employee>>();
		lst.add(new TaskAsCallable(1001));
		lst.add(new TaskAsCallable(1002));
		lst.add(new TaskAsCallable(1003));
		lst.add(new TaskAsCallable(1004));
		lst.add(new TaskAsCallable(1005));
		
		// returns a list of Futures holding their status and results when all complete
		List<Future<Employee>> tasks = executorService.invokeAll(lst);
		
		System.out.println(tasks.size() +" Responses recieved.\n");
		
		for(Future<Employee> task : tasks)
		{
			System.out.println(task.get().toString());
		}
		
		/* shutdown your thread pool, else your application will keep running */
		executorService.shutdown();
		
	}
}

6. Output

Here is the output that i got on my console.
thread-reponse

Advertisements

, , ,

  1. #1 by yunus on December 10, 2014 - 8:18 am

    thanks, i will try

  2. #2 by abuu on January 15, 2015 - 7:13 am

    Nice article !.
    i want to know in your main class , is your program control come to line no 29 only if all task are completed or it may come earlier also ? does it take care of all task completion or i need to use some additional mechanism like countdown latch ?

    • #3 by Bharat Sharma on March 15, 2015 - 8:22 am

      It comes to line 29 only after all threads complete processing. It waits for completion of all tasks and does not need any other mechanism to like latch etc.

  3. #4 by Yudhi Setiawan on April 14, 2015 - 5:34 am

    And how about returning data from database?

  4. #5 by Manoj on June 10, 2016 - 9:37 am

    How to return when implement runnable interface?

    • #6 by Bharat Sharma on June 10, 2016 - 10:28 am

      There are a few tricks:

      1. Pass an arraylist/object as a constructor argument of your runnable object. Now use this arraylist/object to keep storing processed response data in your your run method. After your run method finshes you still hold a reference to the arraylist/object that has processed data.

      2. Store your response in a database table.

      3. Write your response to a file and later read that file.

      4. More left to your imagination.. but would recommend using Callable interface and do it in a simple way.

      Cheers!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: