Introduction
Both Runnable
and Callable
are interface
for multiple-thread in Java. Let’s compare them with code.
The main differences:
Runnable Interface | Callable Interface | |
---|---|---|
Package | java.lang.Runnable since JDK 1.0 | java.util.concurrent.Callable Since JDK 1.5 |
Method | public abstract void run(); |
V call() throws Exception; |
Exception | Can’t Throw an exception; | Can throw an exception; |
Return Value | Can’t return any result; | Can returun the result you want; |
The definition code
Runnable
:
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
Callable
:
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
How to use
Runnable
Implement the interface with overriding the run()
method:
class PkslowRunnable implements Runnable {
private final String name;
PkslowRunnable(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(name + " is running");
try {
Thread.sleep(1000);
System.out.println(name + " is completed");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
We can use ExecutorService
to submit the Runnable task:
private static void runnable() {
ExecutorService executorService = Executors.newFixedThreadPool(4);
executorService.submit(new PkslowRunnable("pkslow.r1"));
executorService.submit(new PkslowRunnable("pkslow.r2"));
executorService.submit(new PkslowRunnable("pkslow.r3"));
executorService.submit(new PkslowRunnable("pkslow.r4"));
executorService.submit(new PkslowRunnable("pkslow.r5"));
executorService.submit(new PkslowRunnable("pkslow.r6"));
executorService.submit(new PkslowRunnable("pkslow.r7"));
executorService.submit(new PkslowRunnable("pkslow.r8"));
executorService.submit(new PkslowRunnable("pkslow.r9"));
executorService.submit(new PkslowRunnable("pkslow.r10"));
awaitTerminationAfterShutdown(executorService);
}
Output:
pkslow.r4 is running
pkslow.r2 is running
pkslow.r3 is running
pkslow.r1 is running
pkslow.r2 is completed
pkslow.r4 is completed
pkslow.r1 is completed
pkslow.r3 is completed
pkslow.r5 is running
pkslow.r6 is running
pkslow.r7 is running
pkslow.r8 is running
pkslow.r5 is completed
pkslow.r7 is completed
pkslow.r6 is completed
pkslow.r8 is completed
pkslow.r10 is running
pkslow.r9 is running
pkslow.r10 is completed
pkslow.r9 is completed
Callable
Implement the Callable
interface with overriding the call()
method:
class PkslowCallable implements Callable<Integer> {
private final String name;
PkslowCallable(String name) {
this.name = name;
}
@Override
public Integer call() throws Exception {
System.out.println(name + " is running");
try {
Thread.sleep(1000);
System.out.println(name + " is completed");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return (new Random().nextInt()) % 100;
}
}
We will return a random int
as a result.
Similarly, we can use ExecutorService
to submit the Callable
task:
private static void callable() {
ExecutorService executorService = Executors.newFixedThreadPool(4);
List<Future<Integer>> futures = new ArrayList<>();
futures.add(executorService.submit(new PkslowCallable("pkslow.c1")));
futures.add(executorService.submit(new PkslowCallable("pkslow.c2")));
futures.add(executorService.submit(new PkslowCallable("pkslow.c3")));
futures.add(executorService.submit(new PkslowCallable("pkslow.c4")));
futures.add(executorService.submit(new PkslowCallable("pkslow.c5")));
futures.add(executorService.submit(new PkslowCallable("pkslow.c6")));
futures.add(executorService.submit(new PkslowCallable("pkslow.c7")));
futures.add(executorService.submit(new PkslowCallable("pkslow.c8")));
futures.add(executorService.submit(new PkslowCallable("pkslow.c9")));
futures.add(executorService.submit(new PkslowCallable("pkslow.c10")));
futures.forEach(ft -> {
try {
System.out.println("Result from Future: " + ft.get());
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
});
awaitTerminationAfterShutdown(executorService);
}
With the Future.get()
, we can fetch the result.
Output:
pkslow.c1 is running
pkslow.c3 is running
pkslow.c2 is running
pkslow.c4 is running
pkslow.c2 is completed
pkslow.c1 is completed
pkslow.c3 is completed
pkslow.c4 is completed
pkslow.c5 is running
pkslow.c7 is running
pkslow.c6 is running
pkslow.c8 is running
Result from Future: 62
Result from Future: 3
Result from Future: -1
Result from Future: 38
pkslow.c7 is completed
pkslow.c6 is completed
pkslow.c8 is completed
pkslow.c5 is completed
pkslow.c10 is running
pkslow.c9 is running
Result from Future: 19
Result from Future: -42
Result from Future: 73
Result from Future: 84
pkslow.c10 is completed
pkslow.c9 is completed
Result from Future: -32
Result from Future: -48
Code
Code in GitHub: https://github.com/LarryDpk/pkslow-samples