I'm learning Java at the moment and I see some code that looks like this:
public interface Await {
boolean await(long timeout, TimeUnit timeUnit) throws InterruptedException;
}
public Await spinServerUp() {
this.startServers()
return (timeout, timeUnit) -> countDownLatch.await(timeout, timeUnit);
}
Now, I understand that countDownLatch
waits for the threads to complete before continuing on.
My question is - how do parameters timeout
and timeunit
get passed to the Lambda expression? I can't find any usage examples on my end for this block of code that I'm reading, so I'm a bit confused.
I'm also not sure if I follow the spinServerUp()
method that well, I understand that it calls this.startServers()
then returns the Lambda expression - thus giving control to the Lambda expression. Why return the Lambda expression, though?
I've tried to do some research and reading, but I got more confused. Any clarifications would be appreciated
CodePudding user response:
how do parameters timeout and timeunit get passed to the Lambda expression?
Just treat the returnValue as a function. Basically same as function you declared in class:
Await await = spinServerUp();
await.await(3, TimeUnit.SECONDS);
Why return the Lambda expression though?
Lambda function declaration does nothing util you call it like code snippet above.
CodePudding user response:
Await
is a Functional interface (i.e. an interface defining only a single abstract method).
And method spinServerUp()
produces an implementation of this Functional interface (which is expressed in the form of Lambda expression).
Hence, in what ever place that requires an instance of Await
you can use a Method reference intanceName::spinServerUp()
, where intanceName
is a reference to the instance of a class that own method spinServerUp()
, also within the owning class you can use this
keyword this::spinServerUp()
.
how do parameters timeout and timeunit get passed to the Lambda expression?
Suppose you have the following method:
public void foo(long timeout, TimeUnit timeUnit, Await a) {
a.await(timeout, timeout);
}
You can call it like that:
foo(5, TimeUnit.MILLI_SCALE, intanceName::spinServerUp()
The parameters require by the Await
contract should be provided by the code that uses it directly by invoking Await.await()
.
I understand that it calls the this.startServers() then returns the Lambda expression - thus giving control to the Lambda expression.
If you mean that you think that while spinServerUp()
gets executed it also fairs the logic of the lambda expression, then it's not correct. A Lambda expression (as well a method references) is just a way to obtain an instance of a Function interface. Lambda basically is an object representing a certain behavior, when you're defining a lambda this behavior doesn't get executed.
In order to actually execute the behavior of a lambda expression, you need to plug the reference to it into a code which would invoke the abstract method of the Function interface it's represents (Await.await()
, Function.apply()
, Predicate.test()
, etc.).
I recommend you to get familiar with these tutorials on Lambda expressions and Method references provided by Oracle
CodePudding user response:
You can use the lamda to invoke the await function:
try {
if (spinServerUp().await(1, MINUTES)) {
// do stuff
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// just exit on interruption?
}