60

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 and TestB 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
  • 16,538
  • 58
  • 164
  • 276
  • 7
    You can use `Void` instead if `void` and return `null` as dummy return value. – nosid Apr 01 '14 at 19:54
  • 1
    You may want to use `Runnable` instead of `Callable`. – ajb Apr 01 '14 at 19:55
  • 1
    @ajb: Can you provide an example if possible how to use Runnable here so that I can execute TestA and TestB in parallel. – AKIWEB Apr 01 '14 at 19:58
  • @ajb `Runnable` may not work in some scenarios. For one: [`ExecutorService#invokeAll`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ExecutorService.html#invokeAll(java.util.Collection)) takes a collection of `Callable` but does *not* take a collection of `Runnable`. – Basil Bourque May 10 '21 at 02:08

3 Answers3

84

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()
nosid
  • 45,370
  • 13
  • 104
  • 134
4

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).

Rogue
  • 9,871
  • 4
  • 37
  • 66
  • Thanks for suggestion. Then can you provide me an example how I can execute TestA and TestB in parallel using Runnable instead of callable? – AKIWEB Apr 01 '14 at 19:57
  • 9
    ExecutorService 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. – nosid Apr 01 '14 at 19:57
  • 4
    Rogue- what's the problem with using callables in this situation? – IcedDante Sep 14 '15 at 15:25
  • 1
    @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 – Rogue Oct 30 '15 at 20:43
  • How does one use `Runnable` with [`ExecutorService#invokeAll​( Collection extends Callable> tasks )`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ExecutorService.html#invokeAll(java.util.Collection))? – Basil Bourque May 10 '21 at 02:10
  • @BasilBourque if you had a list of runnables, then `list.forEach(executor::submit)`; the alternative of wrapping all of those runnables into `Callable` 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 into `Future`s accordingly with return values, `Callable` is appropriate. Just be aware of the exception handling. – Rogue May 10 '21 at 13:59
1

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/

AddJ
  • 43
  • 7