How to use Callable with void return type?
Solution 1
You can use java.lang.Thread for parallel execution. However, in most cases it's easier to use an java.util.concurrent.ExecutorService. The latter provides a method to submit a Callable and returns a Future to get the result later (or wait for completion).
If testA.abc() and testB.xyz() should be executed in parallel, you use the ExecutorService to execute the former in a separate thread whereas the latter is executed in the original thread. Then you wait for the completion of the former for synchronization.
ExecutorService executor = ... // e.g. Executors.newFixedThreadPool(4);
Future<Void> future = executor.submit(new Callable<Void>() {
public Void call() throws Exception {
testA.abc();
return null;
}
});
testB.xyz();
future.get(); // wait for completion of testA.abc()
Solution 2
Why would you need a void for running something in Parallel? For one, if you don't need the return value, you can simply return null
.
To make something parallel you need to use threading/scheduling. I would personally recommend avoiding Callables, and using Runnables instead (and hey, no return value).
Solution 3
A shorter version:
ExecutorService executor = ... // e.g. Executors.newFixedThreadPool(4);
Future<?> future = executor.submit(() -> testA.abc());
testB.xyz();
future.get(); // wait for completion of testA.abc()
To be noted that having to run something in parallel with nothing to be returned could be a sign of a bad pattern :)
Also, if you are in a Spring environment, you could use: https://spring.io/guides/gs/async-method/
Comments
-
AKIWEB almost 2 years
I am working on a project in which I have multiple interface and two Implementations classes which needs to implement these two interfaces.
Suppose my first Interface is -
public Interface interfaceA { public void abc() throws Exception; }
And its implementation is -
public class TestA implements interfaceA { // abc method }
I am calling it like this -
TestA testA = new TestA(); testA.abc();
Now my second interface is -
public Interface interfaceB { public void xyz() throws Exception; }
And its implementation is -
public class TestB implements interfaceB { // xyz method }
I am calling it like this -
TestB testB = new TestB(); testB.xyz();
Problem Statement:-
Now my question is - Is there any way, I can execute these two implementation classes in parallel? I don't want to run it in sequential.
Meaning, I want to run
TestA
andTestB
implementation in parallel? Is this possible to do?I was thinking to use Callable here but not sure how to use Callable with void return type here -
Let's use TestB class as an example:
public interface interfaceB { public void xyz() throws Exception; } public class TestB implements interfaceB, Callable<?>{ @Override public void xyz() throws Exception { //do something } @Override public void call() throws Exception { xyz(); } }
Above code gives compilation error..
UPDATE:-
It looks like lot of people are suggesting to use Runnable instead of callable. But not sure how do I use Runnable here so that I can execute
TestA and TestB
in parallel. -
AKIWEB about 10 yearsThanks for suggestion. Then can you provide me an example how I can execute TestA and TestB in parallel using Runnable instead of callable?
-
nosid about 10 yearsExecutorService is probably the best approach to execute two tasks in parallel. It also supports Runnable. However, Callable has the advantage to also support arbitrary exceptions.
-
IcedDante over 8 yearsRogue- what's the problem with using callables in this situation?
-
Rogue over 8 years@IcedDante I've always avoided them because of their exception handling, which lead to me having to debug stuff just to find out the exception in a callable is being raised and not printed / thrown out of the context
-
Ali Nadalizadeh over 5 yearsVery Nice! I did not know we have a Void class to be used there in the template parameter...
-
Basil Bourque about 3 yearsHow does one use
Runnable
withExecutorService#invokeAll( Collection<? extends Callable<T>> tasks )
? -
Rogue about 3 years@BasilBourque if you had a list of runnables, then
list.forEach(executor::submit)
; the alternative of wrapping all of those runnables intoCallable
objects defeats the purpose in terms of the exception handling comments above. That said,Callable
doesn't need to be avoided completely, if you have a list of objects that you want to render intoFuture
s accordingly with return values,Callable
is appropriate. Just be aware of the exception handling.