Java CompletableFuture chain calls on interface - java

I have some workflow abstraction that relies on an interface WorkflowStep:
public interface WorkflowStep {
public void executeStep();
}
Now I have got three different classes that implement this interface:
GetCoordinatesForWaypoints, DisplayDetails, PlaySounds
My aim is to chain them with CompletableFuture, currently each overriden executeStep() method runs in a runnable, like shown here for example:
public class GetCoordinatesForEndpoints implements WorkflowStep {
#Override
public void executeStep() {
new Thread(new Runnable() {
#Override
public void run() {
//download coordinates from open street map
}).start();
}
}
The other classes methods look similiar. Now I have a central class where the workflow is started. Currently it looks like this:
public class DetailsDispatchWorkflow implements DispatchWorkflow {
private List<WorkflowStep> workflowSteps;
public DetailsDispatchWorkflow() {
workflowSteps = new LinkedList<>();
}
#Override
public void start() {
workflowSteps.add(new GetCoordinatesForEndpoints());
workflowSteps.add(new DisplayDetails());
workflowSteps.add(new PlaySounds());
workflowSteps.forEach(WorkflowStep::executeStep);
}
}
Now I want to replace this with CompletableFutures. The first thing I tried was to do something like this:
ExecutorService executorService = Executors.newFixedThreadPool(5);
CompletableFuture<WorkflowStep> workflowStepCompletableFuture =
CompletableFuture.supplyAsync(() -> new
GetCoordinatesForEndpoints().executeStep(), executorService);
which gives me an error (I think because the called method returns void). Calling only the constructor works. My next step is to chain those calls with thenAccept (because the called actions do not return a value), but that does not work either, when I append
.thenAccept(() -> new DisplayDetails().executeStep(), executorService);
I get an error that the compiler cannot infer the functional interface type. My quesiton is: How can I achieve the following call chain:
CompletableFuture<WorkflowStep> workflowStepCompletableFuture =
CompletableFuture
.supplyAsync(() -> new GetCoordinatesForEndpoints().executeStep(), executorService)
.thenAccept(() -> new DisplayDetails().executeStep(), executorService)
.thenAcceptAsync(() -> new PlaySounds().executeStep(), executorService);
when all instantiated objects implement the same interface?

Your WorkflowStep interface is basically equivalent to Runnable: no input, no output. In the CompletableFuture API, you should thus use the corresponding runAsync() and thenRunAsync() methods:
CompletableFuture<Void> workflowStepCompletableFuture =
CompletableFuture
.runAsync(() -> new GetCoordinatesForEndpoints().executeStep(), executorService)
.thenRunAsync(() -> new DisplayDetails().executeStep(), executorService)
.thenRunAsync(() -> new PlaySounds().executeStep(), executorService);
This will make all of them run asynchronously, but in sequence (as it seems you are trying to do).
Of course you should also remove the Thread creation from your implementation to make this useful.

Related

Run some code before every CompletableFuture.runAsync()

I have an application with a couple runAsync(). These runAsync() call a variety of other methods, and I'd like to run some code before each of them but within the same thread.
So for example I have main thread, then I call runAsync(MyClass::myMethod), Thread1 is created and before myMethod() gets called, within the same thread (Thread1), another method is called.
I assume this would involve some kind of wrapper of some sorts but since this uses lambda expressions and async threads I'm a bit lost on how that'd be done.
Thanks in advance
Edit: I'd like to clarify that methodToRunBeforeAsync() should be hidden from other devs. Something like using a wrapper so you don't have to worry to make the calls to methodToRunBeforeAsync()
In order to run code around those lambdas there are a couple of options. One would be AOP but that can be complex to set up so if you're able to change the calls, you could do the following:
Option 1: Create a WrapperRunnable
Just create a wrapper/decorator that executes whatever additional code you need. You can use that approach wherever a Runnable is required.
class WrapperRunnable implements Runnable {
Runnable delegate;
WrapperRunnable(Runnable r) {
delegate= r;
}
public void run() {
//any code before
delegate.run();
//any code after
}
}
Usage: CompletableFuture.runAsync(new WrapperRunnable(MyClass::myMethod))
Option 2: wrap runAsync()
Provide your own runAsync(Runnable) method that internally creates a decorator lambda or uses the decorator defined in option 1. That calls CompletableFuture.runAsync() internally and can only be used as a replacement for this method.
class MyCompletables {
public static CompletableFuture<Void> runAsync(Runnable runnable) {
return CompletableFuture.runAsync(() -> {
//any code before
runnable.run();
//any code after
});
}
}
Using the decorator of option 1:
class MyCompletables {
public static CompletableFuture<Void> runAsync(Runnable runnable) {
return CompletableFuture.runAsync(new WrapperRunnable(runnable));
}
}
Usage: MyCompletables.runAsync(MyClass::myMethod)
Note that there are other options as well, some being more flexible, some more elegant, but this should get you started while still being easy to understand.
Something like this? Just wrap the task and make sure people use myRunAsync instead of the standard one. Give it a better name, obviously.
public static void main(String[] args) {
myRunAsync(() -> System.out.println("Task")).join();
}
private static CompletableFuture<Void> myRunAsync(Runnable runnable) {
return CompletableFuture.runAsync(() -> {
preTask();
runnable.run();
});
}
private static void preTask() {
System.out.println("Pre");
}
One simple example would be:
runAsync(() -> {
myOtherObject.myMethodToRunBefore();
myObject.myMethod();
}
)
You can either add the call to myMethodToRunBefore() in the first line of the body myMethod() or create wrapper object.The choice depends if the myMethod should be separated from the call to myMethodToRunBefore (then use wrapper) or they always need to be called together in same order (then add the call to the beforeMethod in the first line of myMethod).

How to best implement a multi-thread approach in Spring Boot

I have been struggling with implementing a multi-threaded approach to the application I am working on.
The part I want to run in parallel threads was originally constructed with a for loop going about a list.
#Service
public ApplicationServiceImpl implements ApplicationService {
#Override
public ResponseEntity<Void> startProcess(List<MyObject> myObjectList) throws Exception {
for (MyObject myObject : myObjectList) {
AnotherTypeOfObject anotherTypeOfObject = runMethodA(myObject);
YetAnotherTypeOfObject yetAnotherTypeOfObject = runMethodB(anotherTypeOfObject);
runMethodC(yetAnotherTypeOfObject, aStringValue, anotherStringValue);
runMethodD(yetAnotherTypeOfObject);
}
}
}
The methods private AnotherTypeOfObject runMethodA(MyObject myObject) {...}, private YetAnotherTypeOfObject yetAnotherTypeOfObject(AnotherTypeOfObject anotherTypeOfObject) {...}, private void runMethodC(YetAnotherTypeOfObject yetAnotherTypeOfObject, String aStringValue, String anotherStringValue) {...} and private void runMethodD(MyObject myObject) {...} only use local variables.
I have looked quite a bit to get a solution that would allow firing the threads of a list of 100s of MyObject instead of one after the other.
What I have done is create a:
#Configuration
#EnableAsync
public class AsyncConfiguration() {
#Bean(name = "threadPoolTaskExecutor")
public Executor aSyncExecutor() {
final ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(4);
threadPoolTaskExecutor.setMaxPoolSize(4);
threadPoolTaskExecutor.setQueueCapacity(50);
threadPoolTaskExecutor.setThreadNamePrefix("threadNamePrefix");
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
}
I do have loads of log.info("some recognizable text") through the methods A, B, C and D so I can make sure what is going on and I aggregated these methods into one like
private void runThreads(MyObject myObject, String aStringValue, String anotherStringValue) {
AnotherTypeOfObject anotherTypeOfObject = runMethodA(myObject);
YetAnotherTypeOfObject yetAnotherTypeOfObject = runMethodB(anotherTypeOfObject);
runMethodC(yetAnotherTypeOfObject, aStringValue, anotherStringValue);
runMethodD(yetAnotherTypeOfObject);
}
And I have tried to run the main method as:
#Override
#Async("threadPoolTaskExecutor")
public ResponseEntity<Void> startProcess(List<MyObject> myObjectList) throws Exception {
String aStringValue = myObject.getAStringValue();
String anotherStringValue = myObject.getAnotherStringValue();
myObjectList.forEach(myObject -> runThreads(myObject, aStringValue, anotherStringValue));
}
I still don't get the intended result of firing a few threads for the runThreads(...) {} method, so the processing is done in parallel.
What am I missing here?
Actually you are not parallelising the for loop, but the method that executes the for loop. A single thread in this case would execute all the loop.
You need to put the #Async on top of runThreads()
Although It's not recommended to create the executor with static configurations. Try to use the completablefuture API :
https://www.baeldung.com/java-completablefuture
If it's only for running all elements of a collection in parallel, then you can use Stream.parallel(). It uses a default ForkJoinPool with a thread per CPU core. This is the simplest method introduced in Java 8.
myObjectList.stream()
.parallel()
.forEach(myObject -> runThreads(myObject, myObject.getAStringValue(), myObject.getAnotherStringValue()));
For this you don't need any #Async or Spring-provided Executor.
You can use a custom ForkJoinPool to customize the number of threads, but the default might work well, too.
ForkJoinPool customThreadPool = new ForkJoinPool(4);
customThreadPool.invoke(
() -> myObjectList.stream()
.parallel()
.forEach(myObject -> runThreads(myObject, myObject.getAStringValue(), myObject.getAnotherStringValue())));

How to mock completion of a CompletableFuture in Mockito

I want to mock that some code is being called when a CompletableFuture has completed successfully.
I have this class:
public class MyClassImplementRunner implements Runnable {
private final String param1;
public MyClassImplementRunner(String param1) {
this.param1 = param1;
}
public static CompletableFuture<Void> startAsync(String param1) {
return CompletableFuture.runAsync(
new MyClassImplementRunner(param1)).whenComplete(
(response, throwable) -> {
//some code when complete
});
#Override
public void run () {
//the runnable code
}
}
}
In my Junit (using Mockito and Java 8), I need to mock that
//some code when complete
is called when Future is completed successfully.
Could you provide some indications on how to achieve this?
Extract the code you execute in whenComplete to a field and provide a constructor to replace it.
class Runner implement Runnable {
private final String param;
private final BiConsumer<Void, Throwable> callback;
public Runner(String param) {
this.param = param;
this.callback = this::callbackFunction;
}
Runner(String param, BiConsumer<Void, Throwable> callback) {
this.param = param;
this.callback = callback;
}
public void run() {
CompletableFuture.runAsync(task).whenComplete(callback);
}
private void callbackFunction(Void result, Throwable throwable) {
//some code when complete
}
}
The test will look as follows:
class RunnerTest {
#Test
void test() {
new Runner("param", (response, throwable) -> /* mocked behavior */).run();
}
}
My first inclination is not to mock this: It looks like startAsync is a part of MyClassImplementRunner's public API, and that you should be testing these pieces together. In a test class like MyClassImplementRunnerTest, it makes sense to treat the system under test as MyClassImplementRunner without trying to split it up. Otherwise, it's very easy to lose track of what you're testing, including what is real versus what is a mock.
If there is any external condition that MyClassImplementRunner is looking for, you can mock that dependency, which would likely cause your CompletableFuture to return immediately; however, you've only shown us a single String parameter.
That said, it's possible that startAsync contains logic that you'd like to test exhaustively without a real MyClassImplementRunner. In that case, you could create an overload for testing, possibly with limited visibility or test-only annotations to indicate that it shouldn't be called in production.
public static CompletableFuture<Void> startAsync(String param1) {
return startAsync(new MyClassImplementRunner(param1);
}
/** Package-private, for a test class in the same package. */
#VisibleForTesting static CompletableFuture<Void> startAsync(Runnable task) {
return CompletableFuture.runAsync(task).whenComplete(
(response, throwable) -> {
//some code when complete
});
}
By splitting this up, you can now run startAsync(new Runnable()) in tests to simulate an instantly-succeeding task, and run startAsync(() -> { throw new RuntimeException(); }) to simulate an instantly-failing task. This allows you to test startAsync independently from MyClassImplementRunner.
It may not seem wise to refactor for testing or to introduce test-only methods, and this is a fair assessment: Purely speaking, MyClassImplementRunner should be tested exactly as consumers would run it, without mocking. However, if you're saying it is much more convenient in tests to run with a different Runnable than MyClassImplementRunner, you are in control of the code and you can prepare for this by including the appropriate flexiblity ("testing seam") in the code you control. In fact, if startAsync is a separate-enough method that it can take an arbitrary Runnable, you may choose to separate it out to be a separate method with separate testing.

How to wait for completion of multiple tasks in Java?

What is the proper way to implement concurrency in Java applications? I know about Threads and stuff, of course, I have been programming for Java for 10 years now, but haven't had too much experience with concurrency.
For example, I have to asynchronously load a few resources, and only after all have been loaded, can I proceed and do more work. Needless to say, there is no order how they will finish. How do I do this?
In JavaScript, I like using the jQuery.deferred infrastructure, to say
$.when(deferred1,deferred2,deferred3...)
.done(
function(){//here everything is done
...
});
But what do I do in Java?
You can achieve it in multiple ways.
1.ExecutorService invokeAll() API
Executes the given tasks, returning a list of Futures holding their status and results when all complete.
2.CountDownLatch
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
A CountDownLatch is initialized with a given count. The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is a one-shot phenomenon -- the count cannot be reset. If you need a version that resets the count, consider using a CyclicBarrier.
3.ForkJoinPool or newWorkStealingPool() in Executors is other way
Have a look at related SE questions:
How to wait for a thread that spawns it's own thread?
Executors: How to synchronously wait until all tasks have finished if tasks are created recursively?
I would use parallel stream.
Stream.of(runnable1, runnable2, runnable3).parallel().forEach(r -> r.run());
// do something after all these are done.
If you need this to be asynchronous, then you might use a pool or Thread.
I have to asynchronously load a few resources,
You could collect these resources like this.
List<String> urls = ....
Map<String, String> map = urls.parallelStream()
.collect(Collectors.toMap(u -> u, u -> download(u)));
This will give you a mapping of all the resources once they have been downloaded concurrently. The concurrency will be the number of CPUs you have by default.
If I'm not using parallel Streams or Spring MVC's TaskExecutor, I usually use CountDownLatch. Instantiate with # of tasks, reduce once for each thread that completes its task. CountDownLatch.await() waits until the latch is at 0. Really useful.
Read more here: JavaDocs
Personally, I would do something like this if I am using Java 8 or later.
// Retrieving instagram followers
CompletableFuture<Integer> instagramFollowers = CompletableFuture.supplyAsync(() -> {
// getInstaFollowers(userId);
return 0; // default value
});
// Retrieving twitter followers
CompletableFuture<Integer> twitterFollowers = CompletableFuture.supplyAsync(() -> {
// getTwFollowers(userId);
return 0; // default value
});
System.out.println("Calculating Total Followers...");
CompletableFuture<Integer> totalFollowers = instagramFollowers
.thenCombine(twitterFollowers, (instaFollowers, twFollowers) -> {
return instaFollowers + twFollowers; // can be replaced with method reference
});
System.out.println("Total followers: " + totalFollowers.get()); // blocks until both the above tasks are complete
I used supplyAsync() as I am returning some value (no. of followers in this case) from the tasks otherwise I could have used runAsync(). Both of these run the task in a separate thread.
Finally, I used thenCombine() to join both the CompletableFuture. You could also use thenCompose() to join two CompletableFuture if one depends on the other. But in this case, as both the tasks can be executed in parallel, I used thenCombine().
The methods getInstaFollowers(userId) and getTwFollowers(userId) are simple HTTP calls or something.
You can use a ThreadPool and Executors to do this.
https://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
This is an example I use Threads. Its a static executerService with a fixed size of 50 threads.
public class ThreadPoolExecutor {
private static final ExecutorService executorService = Executors.newFixedThreadPool(50,
new ThreadFactoryBuilder().setNameFormat("thread-%d").build());
private static ThreadPoolExecutor instance = new ThreadPoolExecutor();
public static ThreadPoolExecutor getInstance() {
return instance;
}
public <T> Future<? extends T> queueJob(Callable<? extends T> task) {
return executorService.submit(task);
}
public void shutdown() {
executorService.shutdown();
}
}
The business logic for the executer is used like this: (You can use Callable or Runnable. Callable can return something, Runnable not)
public class MultipleExecutor implements Callable<ReturnType> {//your code}
And the call of the executer:
ThreadPoolExecutor threadPoolExecutor = ThreadPoolExecutor.getInstance();
List<Future<? extends ReturnType>> results = new LinkedList<>();
for (Type Type : typeList) {
Future<? extends ReturnType> future = threadPoolExecutor.queueJob(
new MultipleExecutor(needed parameters));
results.add(future);
}
for (Future<? extends ReturnType> result : results) {
try {
if (result.get() != null) {
result.get(); // here you get the return of one thread
}
} catch (InterruptedException | ExecutionException e) {
logger.error(e, e);
}
}
The same behaviour as with $.Deferred in jQuery you can archive in Java 8 with a class called CompletableFuture. This class provides the API for working with Promises. In order to create async code you can use one of it's static creational methods like #runAsync, #supplyAsync. Then applying some computation of results with #thenApply.
I usually opt for an async notify-start, notify-progress, notify-end approach:
class Task extends Thread {
private ThreadLauncher parent;
public Task(ThreadLauncher parent) {
super();
this.parent = parent;
}
public void run() {
doStuff();
parent.notifyEnd(this);
}
public /*abstract*/ void doStuff() {
// ...
}
}
class ThreadLauncher {
public void stuff() {
for (int i=0; i<10; i++)
new Task(this).start();
}
public void notifyEnd(Task who) {
// ...
}
}

Self-executing Java methods

In JavaScript, it is possible to write a self-executing function like this:
(function foo() {
console.log("bar");
}());
I'm looking to do this in Java. So for example:
// This code does not work obviously
public static void main(String[] args) {
(foo() {
System.out.println("bar");
}());
}
Is there such a thing?
As others have said, there's not much reason to do this in Java, since the reasons for doing it in JavaScript aren't problems in Java. But you could do this in Java 8:
((Runnable)(() -> System.out.println("Hello, world"))).run();
which in essence is the same thing #yshavit's answer did in Java 7.
That javascript isn't really creating a "self-executing" function. It's defining a function, and then immediately executing it.
Java doesn't let you define standalone functions, so you can't do this in Java. You can however declare an anonymous class and immediately execute one of its methods:
new Runnable() {
#Override
public void run() {
System.out.println("hello");
}
}.run();
This is sometimes done with new threads. Something like:
new Thread(new Runnable() {
// override Runnable.run
}).start();
(Though in a lot of cases, you'll want to do better thread management -- submit the runnable to an executor service, for instance.)
You can create helper methods (for e.g. run and get) that will execute your custom function.
use run if function doesn't return anything (side effects) and get otherwise
import java.util.function.Supplier;
public interface MyApp {
static void run(Runnable supp) {
supp.run();
}
static <R> R get(Supplier<R> supp) {
return supp.get();
}
static void test() {
run(() -> System.out.println("bar"));
var v = get(() -> "Hello");
}
}

Categories