ListenableFuture callback execution order - java

Guava's ListenableFuture library provides a mechanism for adding callbacks to future tasks. This is done as follows:
ListenableFuture<MyClass> future = myExecutor.submit(myCallable);
Futures.addCallback(future, new FutureCallback<MyClass>() {
#Override
public void onSuccess(#Nullable MyClass myClass) {
doSomething(myClass);
}
#Override
public void onFailure(Throwable t) {
printWarning(t);
}}, myCallbackExecutor);
}
You can wait for a ListenableFuture to complete by calling its get function. For instance:
MyClass myClass = future.get();
My question is, are all callbacks for a certain future guaranteed to run before the get terminates. I.e. if there is a future with many callbacks on many callback executors registered, will all the callbacks complete before get returns?
Edit
My use case is, I pass a builder around to many classes. Each class populates one field of the builder. I want all fields to be populated asynchronously because each field requires an external query to generate the data for the field. I want the user who calls my asyncPopulateBuilder to receive a Future on which she can call get and be assured that all the fields have been populated. The way I thought to do it is as follows:
final Builder b;
ListenableFuture<MyClass> future = myExecutor.submit(myCallable);
Futures.addCallback(future, new FutureCallback<MyClass>() {
#Override
public void onSuccess(#Nullable MyClass myClass) {
b.setMyClass(myClass);
}
#Override
public void onFailure(Throwable t) {
printWarning(t);
}}, myCallbackExecutor);
}
// Do the same thing for all other fields.
What is the recommended way to block until all fields are populated in such a case?

Callbacks are not guaranteed to run before get returns. More on that below.
As for how to address this use case, I would suggest turning the query for each field's data into a separate Future, combining them with allAsList+transform, and taking action on that. (We may someday provide a shortcut for the "combine" step.)
ListenableFuture<MyClass> future = myExecutor.submit(myCallable);
final ListenableFuture<Foo> foo =
Futures.transform(
future,
new Function<MyClass, Foo>() { ... },
myCallbackExecutor);
final ListenableFuture<Bar> bar = ...;
final ListenableFuture<Baz> baz = ...;
ListenableFuture<?> allAvailable = Futures.allAsList(foo, bar, baz);
ListenableFuture<?> allSet = Futures.transform(
allAvailable,
new Function<Object, Object>() {
#Override
public Object apply(Object ignored) {
// Use getUnchecked, since we know they already succeeded:
builder.setFoo(Futures.getUnchecked(foo));
builder.setFoo(Futures.getUnchecked(bar));
builder.setFoo(Futures.getUnchecked(baz));
return null;
}
}
};
Now the user can call allSet.get() to await population.
(Or maybe you want for allSet to be a Future<Builder> so that the user is handed a reference to the builder. Or maybe you don't need a full-on Future at all, only a CountDownLatch, in which you could use addCallback instead of transform and count down the latch at the end of the callback.)
This approach may also simplify error handling.
RE: "Do callbacks run before get?"
First, I am pretty sure that we don't guarantee this anywhere in the spec, so thanks for asking rather than just going for it :) If you do end up wanting to rely on some behavior of the current implementation, please file an issue so that we can add documentation and tests.
Second, if I take your question very literally, what you're asking for isn't possible: If get() waits for all listeners to complete, then any listener that calls get() will hang!
A slightly more lenient version of your question is "Will all the listeners at least start before get() returns?" This turns out to be impossible, too: Suppose that I attach two listeners to the same Future to be run with directExecutor(). Both listeners simply call get() and return. One of the listeners has to run first. When it calls get(), it will hang, since the second listener hasn't started yet -- nor can it until the first listener is done. (More generally, it can be dangerous to rely on any given Executor to execute a task promptly.)
A still more lenient version is "Will the Future at least call submit() for each of the listeners before get() returns?" But this ends up with a problem in the same scenario as I just described: Calling submit(firstListener) on a directExecutor() runs the task and calls get(), which can't complete until the second listener is started, which can't happen until the first listener completes.
If anything, it's starting to sound much more likely that get() will return before any listeners execute. But thanks to the unpredictability of thread scheduling, we can't rely on that, either. (And again: It's not documented, so please don't rely on it unless you ask for it to be documented!)

final Builder b;
CountDownLatch latch = new CountDownLatch(1);
ListenableFuture<MyClass> future = myExecutor.submit(myCallable);
Futures.addCallback(future, new FutureCallback<MyClass>() {
#Override
public void onSuccess(#Nullable MyClass myClass) {
b.setMyClass(myClass);
latch.countDown();
}
#Override
public void onFailure(Throwable t) {
printWarning(t);
latch.countDown();
}, myCallbackExecutor);
try {
latch.await();
} catch (InterruptedException e) {
LOG.error("something InterruptedException", e);
} finally {
myCallbackExecutor.shutdown();
}
Edit
code is inspired by #Chris Povirk
(Or maybe you want for allSet to be a Future so that the user is handed a reference to the builder. Or maybe you don't need a full-on Future at all, only a CountDownLatch, in which you could use addCallback instead of transform and count down the latch at the end of the callback.)
This approach may also simplify error handling.

Related

How does Java guarantee callback is called when future.isDone() in ListenableFuture

when going through the ListenableFutre interface, it notes in the doc that
addListener()
Registers a listener to be run on the given executor. The listener
will run when the Future's computation is complete or, if the
computation is already complete, immediately.`
Since Future.get() is a blocking call, how does Java guarantee certain future is Done? are they spinning on this? I understand that with Framework like dagger producers, it is kinda easy to understand (once task is done, write to something, the monitoring thread will be notified). in ListenableFuture case, does jvm support something like this out of box?
using wait()/notify() like mechanism ?
FollowUp Question: as all of you put, it is the caller actually guarantee the listener to be run, normal case to use a ListenableFuture
would be ListenableFuture future = Caller.call(), with caller and callee in different threads or even in different JVMs, how is this done in java? the listener in stored in both the caller thread and callee thread ? or using remote reigstery when in differnt JVMs?
There's nothing magic going on with ListenableFuture - the contract of the interface simply requires that any implementations invoke any registered listeners upon completion (or immediately, if already done).
It may help to look at one such implementation, AbstractFuture - specifically look at the .complete() method, which is invoked immediately after the future becomes "done" (by finishing, failing, or being cancelled). In order to be both fast and thread-safe the details are somewhat complex, but essentially that's all it does.
As already mentioned, the best way to understand the ListenableFuture is to look how it is implemented. When you call addListener(Runnable listener, Executor exec), you provide a Runnable listener and an Executor to run this listener, so it is you who decides how your listener is executed.
the listener is stored in both the caller thread and callee thread ?
The listener is stored inside the future, in the ExecutionList:
// The execution list to hold our executors.
private final ExecutionList executionList = new ExecutionList();
And addListener(Runnable listener, Executor exec) does just following:
public void addListener(Runnable listener, Executor exec) {
executionList.add(listener, exec);
}
So when the future completes, it calls the set(V value) method:
protected boolean set(#Nullable V value) {
boolean result = sync.set(value);
if (result) {
executionList.execute();
}
return result;
}
and all listeners are executed like this: executor.execute(runnable);
I'd like to add answers.
Guava does not garantee it.
If you down JVM or JVM is crashed no listeners would be invoked.
If you shutdown executor without cancelling futures, no listeners would be invoked too. I mean this case:
ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(false);
return t;
}
});
ListenableFuture<?> listenableFuture = JdkFutureAdapters.listenInPoolThread(
executorService.submit(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("run!!!");
}
}),
executorService
);
Futures.addCallback(listenableFuture, new FutureCallback<Object>() {
#Override
public void onSuccess(#Nullable Object result) {
System.out.println("onSuccess");
}
#Override
public void onFailure(Throwable t) {
System.out.println("onFailure");
}
});
MoreExecutors.shutdownAndAwaitTermination(executorService, 3, TimeUnit.SECONDS);
I didn't see "onSuccess" or "onFailure", did you?
In usual workflow when JVM is running, Guava uses CAS to invoke listeners exactly once, you can see it in source code too.

Listenablefuture vs Completablefuture

I tried hard but didn't find any article or blog which clearly compares ListenableFuture and CompletableFuture, and provides a good analysis.
So if anyone can explain or point me to such a blog or article, it will be really good for me.
Both ListenableFuture and CompletableFuture have an advantage over its parent class Future by allowing the caller to "register" in one way or another a callback to be called when the async action has been completed.
With Future you can do this:
ExecutorService executor = ...;
Future f = executor.submit(...);
f.get();
f.get() gets blocked until the async action is completed.
With ListenableFuture you can register a callback like this:
ListenableFuture listenable = service.submit(...);
Futures.addCallback(listenable, new FutureCallback<Object>() {
#Override
public void onSuccess(Object o) {
//handle on success
}
#Override
public void onFailure(Throwable throwable) {
//handle on failure
}
})
With CompletableFuture you can also register a callback for when the
task is complete, but it is different from ListenableFuture in that it can be completed from any thread that wants it to complete.
CompletableFuture completableFuture = new CompletableFuture();
completableFuture.whenComplete(new BiConsumer() {
#Override
public void accept(Object o, Object o2) {
//handle complete
}
}); // complete the task
completableFuture.complete(new Object())
When a thread calls complete on the task, the value received from a call to get() is set with the parameter value if the task is not already completed.
Read about CompletableFuture
Guava AbstractFuture has its limitations:
Listener is lists, but usually only 1 used - overkill. If multiple listeners are needed, handle it inside the next stage, or think about messaging.
setException set return value as Exception, so user has to use instanceof to differentiate Exception or not at get() like guava AbstractFuture did.
In Future pipeline, too many layers addListener() make code hard to read.
I prefer CompletableFuture.supply().thenApply().thenAccept().handle()

How can I safely decorate an existing callback?

Suppose I'm working with the following callback API:
/**
* Registers a new action which will be run at some later time on
* some other thread, clearing any previously set callback action.
*
* #param callback an action to be run later.
* #returns the previously registered action.
*/
public Runnable register(Runnable callback);
I'd like to register my own action, but I want to preserve any set behavior. In other words I'd like my action to look something like:
new Runnable() {
public void run() {
// do my work
originalCallback.run();
}
}
What's the cleanest way to provide originalCallback to my Runnable?
The naive solutions that come to mind risk introducing a window of time where originalCallback isn't available when the callback is called, or that involve some intricate locking.
After some more digging I found Guava's SettableFuture and Java 8's CompletableFuture. I'll leave my BlockingSupplier up for posterity, but either of these Future implementations would be more standard, and work just the same.
You basically need a holder class with a blocking get() method. Something like this:
public class BlockingSupplier<E> implements Supplier<E> {
private final CountDownLatch latch = new CountDownLatch(1);
private volatile E value;
public synchronized void set(E value) {
checkState(latch.getCount() > 0, "Cannot call set more than once.");
this.value = value;
latch.countDown();
}
#Override
public E get() {
latch.await(); // will block until set() is called
return value;
}
}
Then you can use it like so:
BlockingSupplier<Runnable> supplier = new BlockingSupplier<>();
// Pass the BlockingSupplier to our callback
DecoratorCallback myAction = new DecoratorCallback(supplier);
// Register the callback, and set the BlockingSupplier to the old callback
supplier.set(register(myAction));
Where DecoratorCallback's run() looks like this:
public void run() {
// do my work
// This will block until supplier.set() returns
originalCallbackSupplier.get().run();
}
As durron597 mentions there are better ways to design a callback API, but given the API in the question, this seems reasonable.
This is a terrible way to have an API. The Single Responsibility Principle applies here. The way you are doing it now, your runnable is responsible for:
Whatever it's other job is
Calling the other callback.
You are breaking SRP inherently in your API design! Every class that uses this API is already broken from the getgo.
Fortunately, you can easily solve this problem with Guava's ListenableFuture, which works like this:
Submit the task
Get ListenableFuture object back
Attach callbacks with Futures.addCallback
Doing it this way ensures that your system puts the code for managing multithreading and happensBefore relationships in one place, and the code that actually does the work in another.

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());
}
}

How to make a thread return arraylist of objects in java?

I want a thread to return list. I cant use the run method as its return type is void. I am using the thread in a separate private method inside a class under which the caller method of the thread is also there. The caller needs the list from thread result to do some manipulation. here is my thread. Pls help me in understanding how can i return list from this thread.
private List<myObject> fetchmyObjList(final String abc){
new Thread(new Runnable() {
#Override
public void run() {
try {
List<myObject> myObjList = anotherInternalMethod(abc);
} catch (Exception e) {
System.out.println(e);
}
}
}).start();
}
how can i make this thread return myObjList to the caller?? Please help.
You need Callable instead of Runnable.
Here is an how-to-use callable: https://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6
Use callable instead of Runnable. The function is capable of returning a value in the form of Futures. You can utilize this to achieve your own purpose.
You can push your data to external object (like object which have fetchmyObjList) using just a method like:
List<myObject> myObjList = anotherInternalMethod(abc);
setFetchedObjects(myObjList);
This is a scenerio when you puts controll to newly created thread. We can call it simplivied observer pattern - outer object is notified by method call when data is available. But remember about thread safety in this scenerio!
Other scenerio is to use Callable<OBJECT YOU WANT TO RETURN> and use a Thread/ExecutorService to start your task. Then (in control in your outer object) you can use Callable .get() to get your result.
You cen use blocking or nonblocking methods to wait for result or to check if result is ready to receive from background task.
Of course in your scenerio, creating a Thread with Callable just to block original thread and wait to task completion to return your objects from method, gives nothing - it would be better to not use threads at all.
If you want to perform background operation, change your method signature to return null + call a "listener" method when data will be ready or return a Callable<List<myObject>> and retreive data from it after some other operations done in pararell.
You need to rethink what you're doing. The new thread will run in parallel with the old one, and may not have an answer ready until the calling thread's got a lot more work done. You could make the calling thread wait, but why not just call 'anotherInternalMethod' from the main thread?
You could do something like this (but don't!):
private void fetchmyObjList(final String abc, final List<myObject>[] retList) {
new Thread(new Runnable() {
#Override
public void run() {
try {
retList = anotherInternalMethod(abc);
} catch (Exception e) {
System.out.println(e);
}
}
}).start();
}
but the passed retList object (a one-element array) will not get set correctly until some unpredictable time in the future.
This can be solved by the Callable interface in place of Runnable, and retrieving the value with a Future object, which also lets you wait until the value has been computed. You can achieve this with an ExecutorService.

Categories