How to write a Thread Runnable and Callable Implementations and submit the same to JAVA Executor Interface for execution.
file 1. SimpleThread.java [A simple Runnable implementation that simulates execution by simply sleep of random milisecs. Problem with runnable, is runnable task can neither throw an exception nor return any object. Hence we need Callable Interface from java.util.concurrent package.]
import java.util.concurrent.ThreadLocalRandom;
public class SimpleThread implements Runnable {
private int id;
final private long MAX_SLEEP_MS = 6000;
public SimpleThread(int id) {
this.id = id;
}
@Override
public void run() {
System.out.println(this.id + "====started===");
long sleepTime = 0l;
try {
sleepTime = ThreadLocalRandom.current().nextLong(0, 10) * 1000;
if (sleepTime > MAX_SLEEP_MS) {
System.out.println("Thread is taking more time(" + sleepTime + ") than specified(" + MAX_SLEEP_MS + " ms). Thread ID: " + id);
}
Thread.sleep(sleepTime);//simulates work in progress
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.id + "====stopped== after= " + sleepTime);
}
}
file 2. SimpleCallable.java [Its a simple implementation of Callable interface that has a call function similar to run in Runnable. Only difference/advantage is that call can return an specific type of object and can throw any exception as well.]
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadLocalRandom;
public class SimpleCallable implements Callable<String> {
private int id;
final private long MAX_SLEEP_MS = 2000;
public SimpleCallable(int id) {
this.id = id;
}
@Override
public String call() throws Exception {
System.out.println(this.id + "====started===");
long sleepTime = 0l;
sleepTime = ThreadLocalRandom.current().nextLong(0, 10) * 1000;
if (sleepTime > MAX_SLEEP_MS && id > 3) {
throw new Exception("Terminating, coz a thread is taking more time(" + sleepTime + ") than specified(" + MAX_SLEEP_MS + " ms). Thread ID: " + id);
}
Thread.sleep(sleepTime);//simulates work in progress
return id + "ret after : " + sleepTime;
}
}
file 3. TestExecutorAPI.java [This calls both(callable & runnable) implementations sequentially and at last prints time taken to complete execution for both. If any exception in any callable thread is encountered, Executor stops.]
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class TestExecutorAPI {
private static long threadExecTime = 0l;
private static long callableExecTime = 0l;
public static void main(String[] args) throws Exception {
TestExecutorAPI testExecutorAPI = new TestExecutorAPI();
testExecutorAPI.runThreads();
testExecutorAPI.runCallables();
System.out.println(" time for threads : " + threadExecTime);
System.out.println(" time for callables : " + callableExecTime);
}
private void runCallables() {
long start = System.currentTimeMillis();
ExecutorService executorService = Executors.newFixedThreadPool(5);
List<Future<String>> rows = new ArrayList<>();
try {
for (int i = 0; i < 10; i++) {
SimpleCallable simpleCallable = new SimpleCallable(i);
Future<String> f = executorService.submit(simpleCallable);
rows.add(f);
}
executorService.shutdown();
for (Future<String> future : rows) {
System.out.println(future.get());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
while (!executorService.isTerminated()) {
try {
executorService.awaitTermination(5, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
}
long end = System.currentTimeMillis();
callableExecTime = end - start;
}
private void runThreads() {
long start = System.currentTimeMillis();
ExecutorService executorService = Executors.newCachedThreadPool();
try {
for (int i = 0; i < 10; i++) {
SimpleThread simpleThread = new SimpleThread(i);
executorService.submit(simpleThread);
}
executorService.shutdown();
} catch (Exception e) {
e.printStackTrace();
} finally {
while (!executorService.isTerminated()) {
try {
executorService.awaitTermination(5, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
}
long end = System.currentTimeMillis();
threadExecTime = end - start;
}
}
Download above sources from here.