Run some code before every CompletableFuture.runAsync() - java

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

Related

How to run two asynchronus task synchronously

I am new to multithreading concept in java(springboot) and have a scenario to solve.There is a function in which 2 asynchronus functions are called.I want to make their execution happen synchronously.eg:
public void func(){
call1();
call2();
}
#Async
public void call1(){}
#Async
public void call2(){}
Can anyone please suggest a method to achieve this functionality.
Thanks
Not exactly sure whats the motivation over here, but from what I could understand from the question, the objective seems like that you dont want to block the main thread (thread executing func()), and at the same time achieve serial execution of call1() and call2(). If thats what you want, you could perhaps make call1() and call2() synchronous (i.e. remove the #Async annotation), and add a third asynchronous method (callWrapper() perhaps), and invoke call1() and call2() serially in that method.
You can wait on #Async methods if you change them to return a Future. For example like this:
#Component
class AsyncStuff {
#Async
public ListenableFuture<?> call1() {
/** do things */
return AsyncResult.forValue(null);
}
#Async
public ListenableFuture<?> call2() {
/** do other things */
return AsyncResult.forValue(null);
}
}
#Component
class User {
#Autowired
AsyncStuff asyncStuff; // #Async methods work only when they are in a different class
public void use() throws InterruptedException, ExecutionException {
asyncStuff
.call1() // starts this execution in another thread
.get(); // lets this thread wait for the other thread
asyncStuff
.call2() // now start the seconds thing
.get(); // and wait again
}
}
But it's guaranteed to be slower than simply doing all this without async because all this adds is overhead to move execution between threads. The calling thread could instead of waiting for other threads to do things simply execute the code itself in that time.

Function as a function parameter in Java

I have a class, with Thread as superclass, I pass a function as a parameter and this class just execute that function. This class uses it to create threads, so I can execute any function in a thread without having to create a different class.
public class ThreadEjecucionLambda extends Thread {
Runnable funcion;
public ThreadEjecucionLambda(Runnable funcion)
{
this.funcion=funcion;
}
public void run()
{
funcion.run();
}
}
Now, to create several threads of a same method I use a 'for' block, for example:
for(Computer computer: Persistencia.getListComputers())
{
ThreadEjecucionLambda hilolambda=new ThreadEjecucionLambda(()->logica.EnciendeMonitor(computer.getNombrePC()));
hilolambda.run();
}
What I want to achieve is to generalice the previous 'for' so that I can execute a method,to which I will pass ,as parameters, (following the example) a list of 'Computers' and a function. This method will execute the 'for' block and will create a thread for each 'Computer, so I will pass as a parameter the previous function to the thread and that function will have, as a parameter, the 'Computer'.
What I want to get is something like this (WARNING: IT'S WRONG):
public void EjecutaHilosLambdaSegundo(ArrayList<Computer> listapcs,Runnable funcion)
{
for(Computer computer: listapcs)
{
ThreadEjecucionLambda hilolambda=new ThreadEjecucionLambda(funcion(computer));
hilolambda.run();
}
}
I hope I have explained myself well because it's a very confusing problem.
Thread already has a constructor taking a Runnable as argument, and executing it when you start it, so your subclass is useless and confusing. Not only that, but you never actually start any thread. So you could just run the Runnable directly, without creating any Thread or ThreadEjecucionLambda.
If I understand correctly, you want to execute the same function, taking a Computer as argument, on a list of Computers.
You don't need a Thread to do that. All you need is a Consumer<Computer>:
public consumeAllComputers(List<Computer> computers, Consumer<? super Computer> function) {
computers.forEach(function);
}
But, as you see, this method is useless, since you could just call forEach on the List directly.
So, suppose you want to print the name of each computer in a list, you would use
computers.forEach(computer -> System.out.println(computer.getName());
Don't reinvent the wheel!
For the synchronous solution, look at #JB Nizet answer.
Asynchronous solution
First, your ThreadEjecucionLambda class is not creating thread, because to start a new thread, you need to call the start() method of Thread.
public class ThreadEjecucionLambda extends Thread {
Runnable funcion;
public ThreadEjecucionLambda(Runnable funcion)
{
super(funcion);
this.funcion = funcion;
}
public void run()
{
super.start();
}
}
Second, this class is meaningless! Thread is already working that way.
Third, Runnable as is does not accept argument. What you actually need to do is create your own Runnable that takes a Computer as an argument.
public class MyRunnable implements Runnable {
Computer computer;
public MyRunnable(Computer computer)
{
this.computer = computer;
}
#Override
public void run()
{
// Do what you want cause a pirate is-
// Erm do what you want with your computer object
}
}
And then use it for your above method.
public void EjecutaHilosLambdaSegundo(ArrayList<Computer> listapcs, MyRunnable myRunnable)
{
for(Computer computer: listapcs)
{
Thread myThread = new Thread(myRunnable);
myThread.start();
}
}

Adding multi-threading possibility to a single-threaded all-files-in-directory iterator utility function

I have a function that serially (single-threaded-ly) iterates through a directory of files, changing all tab indentation to three-space indentation.
I'm using it as my first attempt at multi-threading. (Am most of the way through Java Concurrency in Practice...surprised it's eight years old now.)
In order to keep it's current single-threaded functionality, but add in the additional possibility of multi-threading, I'm thinking of changing the function to accept an additional Executor parameter, where the original single-threaded function would now be a call to it, passing in a single threaded executor.
Is this an appropriate way to go about it?
If you're using Java 8, I've found parallelStream to be about the easiest way to implement multi-threading
List<File> files = Arrays.asList(getDirectoryContents());
files.parallelStream().forEach( file -> processFile(file));
If you want to be able to change between single-threaded and multi-threaded, you could simply pass a boolean flag
List<File> files = Arrays.asList(getDirectoryContents());
if(multithreaded){
files.parallelStream().forEach( file -> processFile(file));
}else{
files.stream().forEach(file -> processFile(file));
}
I wish I could help with Java 7, but I went from Java 5 to 8 overnight. :) Java 8 is sooooooo worth it.
One way is as #Victor Sorokin suggests in his answer: wrap the processing of every file in a Runnable and then either submit to an Executor or just invoke run() from the main thread.
Another possibility is to always do the same wrapping in a Runnable and submit it to an always-given Executor.
Whether processing of each file is executed concurrently or not would depend on the given Executor's implementation.
For parallel processing, you could invoke your function passing it i.e. a ThreadPoolExecutor as an argument, whereas for sequential processing you could pass in a fake Executor, i.e. one that runs submitted tasks in the caller thread:
public class FakeExecutor implements Executor {
#Override
public void execute(Runnable task) {
task.run();
}
}
I believe this way is the most flexible approach.
Most straight-forward way:
(The most tricky part) Make sure code is thread-safe. Unfortunately, it's hard to give more concrete advice w/o seeing actual code in question;
Wrap code into Runnable\Callable (either anonymous class or explicit class which implements Runnable\Callable;
This way you'll be able either call your Runnable in main thread (single-threaded version) or pass it to an Executor (multi-threaded version).
One of the ways to create a class implements Executor interface which will execute your code in the main thread. Like this:
public class FileProcessor implements Runnable {
private final File file;
public FileProcessor(File file) {
this.file = file;
}
#Override
public void run() {
// do something with file
}
}
public class DirectoryManager {
private final Executor executor;
public DirectoryManager() {
executor = new Executor() {
#Override
public void execute(Runnable command) {
command.run();
}
};
}
public DirectoryManager(int numberOfThreads) {
executor = Executors.newFixedThreadPool(numberOfThreads);
}
public void process(List<File> files) {
for (File file : files) {
executor.execute(new FileProcessor(file));
}
}
}
and call it in your code like this
DirectoryManager directoryManager = new DirectoryManager();
directoryManager.process(lists);
// some other sync code
or this
DirectoryManager directoryManager = new DirectoryManager(5);
directoryManager.process(lists);
// some other async code

JUnit test of a java asyncron method

Today I had to write a method which get a String as a parameter, make a new thread and write it out to the consol after 5 seconds waiting, so something like this:
public void exampleMethod(final String str){
Runnable myRunnable = new Runnable(){
public void run(){
try {
Thread.sleep(5000);
System.out.println(str);
} catch (InterruptedException e) {
//handling of the exception
}
}
};
Thread thread = new Thread(myRunnable);
thread.start();
//some other things to do
}
My question is: How can I test and what should I test in here with JUnit?
Thank you!
There is nothing complex in this method. You are only using standard API-methods: Thread.sleep, System.out.println, ...
The parameter is just printed, you don't modify it nor use it for a calculation or another method.
There are no side-effects to your own written code, just to the STL.
And there is no result of the method, which you could test.
In my opinion it is not necessary and not simply possible to test it.
The only thing you could test (and even that wouldn't be trivial), is, if after an amount of time the String is printed.
[...] JUnit finishes execution while the thread is still alive. There could have been problems down the line, toward the end of that thread's execution, but your test would never reflect it.
The problem lies in JUnit's TestRunner. It isn't designed to look for Runnable instances and wait around to report on their activities. It fires them off and forgets about them. For this reason, multithreaded unit tests in JUnit have been nearly impossible to write and maintain.
Well, the source - this article - is from 2003 and there's no guarantee that this hasn't been fixed yet, but you may try it out yourself.
My suggestion would be:
Run your code and measure the time it takes. Then add some 1000 milliseconds and but a Thread.sleep(executionTime+1000); after you started you asynchronous task. Not that elegant, but should work in practice. If you want more elegance here (and waste less time), you may want to look for framework that provide a solution.
...Or if you start your Thread directly in the test, you may also use Thread.join to wait, but you will have cases, where you aren't able to do that.
EDIT:
Also check this article, which could provide a solution to pipe those errors to the main thread:
public class AsynchTester{
private Thread thread;
private volatile Error error;
private volatile RuntimeException runtimeExc;
public AsynchTester(final Runnable runnable) {
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
runnable.run();
} catch (Error e) {
error = e;
} catch (RuntimeException e) {
runtimeExc = e;
}
}
});
}
public void start() {
thread.start();
}
public void test() throws InterruptedException {
thread.join();
if (error != null)
throw error;
if (runtimeExc != null)
throw runtimeExc;
}
}
Use it like that:
#Test
public void test() throws InterruptedException {
AsynchTester tester = new AsynchTester(new Runnable() {
#Override
public void run() {
//async code
}
});
tester.start();
tester.test();
}
The issue here is that you are trying to test an interaction instead of a simple returned result or a state change. However, that does not mean it can't be done.
The standard out PrintStream can be replaced with System.setOut(). You can inject your own mock implementation that would allow you verify that the String was written to the stream. You just have to be careful, since this changes the global state, it might effect other code or tests that rely on standard output. At a minimum, you will have to put back the original stream. But things might get more complicated if tests are running in parallel.
This takes us to the next issue, the sleep. There isn't a strong guarantee to how long a sleep will block. This means your test would have to provide some buffer to ensure that the thread had time to write the String before checking the state of the mock stream. You don't want your test to be flaky because of some execution timing jitter. So you would have to decide what buffer you would consider acceptable.
An alternative approach would be to change the implementation of the code so that it is easier to test.
The simplest way to do this is to remove all the static dependencies. Instead of explicitly referencing System.out, the class could be initialized with with an PrintStream to write to. Additionally, you could define an interface that would wrap Thread.sleep(). For testing purposes, you can initialize the class with the mock stream and no-op implementation of the sleep interface. However, you may still have some timing issues as you need the newly created thread to execute before continuing the test.
The other thing you can do is take a step back and decide how much you care about this code being tested. There are only 4 interesting lines of code in this sample and none of them are complicated. Having a code review could be sufficient to ensure there are no bugs.
However, if the business logic is more complicate than writing to standard out, you might decided that testing that is important. The good news is that scheduling a task in an executor is straight forward and that is the part that is making the testing hard. You could make an abstraction that encompasses the scheduling of the task in a background thread. Then provide yourself with more direct access to the business logic in order to test that.
I have often solved that, by providing a ResultTarget which implements an interface IResultTarget to the thread,
In productive code the result will be a list that contains the calculation result. (or null)
In your unit test the ResultTarget is the unit test class itself, which then easily can check the received result.
public Interface IResultTarget {
List getResult();
}
public void ThreadTest extends TestCase implements IResultTarget {
List result;
public List getResult(
return this.result;
}
public void testThread() {
MyRunnable myRunnable= new MyRunnable ();
myRunnable.setResultTarget(this);
Thread thread = new Thread(myRunnable);
thread .start();
Thread.sleep(5 * 1000);
// expecting one element as result of the work of myRunnable.
assertEquals(1, result.size());
}
}

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