ExecutorService – Callable and Runnable Example
In this article let us see an example using Runnable and Callable tasks using ExecutorService.

Please refer here for Overview of ExecutorService

Runnable Example
Runnable does not return any value and cannot throw checked exceptions

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;

public class ExecService {

	public static int totalAmount = 5;

	public void deposit(int amount) {
		System.out.println("Amount is getting Deposited: " + amount + " 
                                Deposited by: " + Thread.currentThread().getName());
		totalAmount = totalAmount + amount;
		System.out.println("Total amount after deposited: " + totalAmount);
	}

	public void withdraw(int amount) {
		System.out.println("Amount to be withdrawn: " + amount + " withdraw by: " 
                        + Thread.currentThread().getName());
		if (totalAmount > 0 && totalAmount >= amount) {
			System.out.println("Amount available to withdraw from total amount: " 
                                           + totalAmount);
			totalAmount = totalAmount - amount;
			System.out.println("Available total amount after withdraw: " + totalAmount);
		} else {
			System.out.println("Unable to withdraw amount, as balance is less");
		}
	}

	public static void main(String args[]) {

		ExecService execService = new ExecService();
		ExecutorService executorService = Executors.newFixedThreadPool(2);
		Runnable runnableTask = () -> {
			try {
				execService.deposit(1);
				execService.withdraw(3);
			} catch (Exception e) {
				e.printStackTrace();
			}
		};

		try {
			IntStream.rangeClosed(0, 6).forEach(s -> {
				try {
					executorService.execute(runnableTask);
					Thread.sleep(1000);
				} catch (Exception e) {
					e.printStackTrace();
				}
			});

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("Shutting down executorservice...");
			executorService.shutdown();
			System.out.println("executor service is alive? "+ executorService.isShutdown());
		}
	}
}

Output:

NOTE:
From the output, we can notice how the executorservice works. We haven’t used Synchronized keyword in any of our methods, but ExecutorService makes sure one thread accesses the methods at a time.

Callable Example
Callable can return Future objects and can throw checked exceptions

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.stream.IntStream;

public class ExecService {

	public static int totalAmount = 5;

	public void deposit(int amount) {
		System.out.println("Amount is getting Deposited: " + amount + " 
                                 Deposited by: " + Thread.currentThread().getName());
		totalAmount = totalAmount + amount;
		System.out.println("Total amount after deposited: " + totalAmount);
	}

	public void withdraw(int amount) {
		System.out.println("Amount to be withdrawn: " + amount + " 
                                   withdraw by: " + Thread.currentThread().getName());
		if (totalAmount > 0 && totalAmount >= amount) {
			System.out.println("Amount available to withdraw from total amount: " 
                                          + totalAmount);
			totalAmount = totalAmount - amount;
			System.out.println("Available total amount after withdraw: " + totalAmount);
		} else {
			System.out.println("Unable to withdraw amount, as balance is less");
		}
	}

	public static void main(String args[]) {

		ExecService execService = new ExecService();

		ExecutorService executorService = Executors.newFixedThreadPool(2);
		
		Callable callableTask = () -> {
			try {
				execService.deposit(1);
				execService.withdraw(3);
				return "Success";
			} catch (Exception e) {
				e.printStackTrace();
				return "Failure";
			}
		};

		try {
			IntStream.rangeClosed(0, 6).forEach(s -> {
				try {
					Future<String> future = executorService.submit(callableTask);
					if(future.get().equalsIgnoreCase("Success")) {
						System.out.println("The task is a success...");
					} else {
						System.out.println("Task Failed...");
					}
					Thread.sleep(1000);
				} catch(Exception e) {
					e.printStackTrace();
				}
				
			});

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("Shutting down executorservice...");
			executorService.shutdown();
			System.out.println("executor service is alive? "+executorService.isShutdown());
		}
	}
}

Output:

We  have used future object to return string, Future object can return Integer, Boolean etc.
Sample example of using Boolean for the above code,

	IntStream.rangeClosed(0, 5).forEach(s -> {
		try {
			Future<Boolean> future = executorService.submit(callableTask);
			if(future.get().booleanValue()==true) {
			   System.out.println("The task is a success...");
			} else {
			   System.out.println("Task Failed...");
			}
			Thread.sleep(1000);
		} catch(Exception e) {
			e.printStackTrace();
		}
				
	});

 

By Sri

Leave a Reply

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