Sometimes I want to trigger a Runnable as part of my Observable sequence, but the Runnable does not report progress.
I have written a simple factory for wrapping a Runnable object into an Observable:
public static <T> Observable<T> fromRunnable(final Runnable action) {
if (action == null) {
throw new NullPointerException("action");
}
return Observable.fromPublisher(subscriber -> {
try {
action.run();
subscriber.onComplete();
} catch (final Throwable throwable) {
subscriber.onError(throwable);
}
});
}
Usage:
Observable.concat(
someTask,
MoreObservables.fromRunnable(() -> {
System.out.println("Done. ");
}));
But does RxJava 2 provide this functionality already?
There is no such factory method for Observable, but Completable could be made from Runnable. So you could create a Completable first and then convert it to Observable:
Observable.concat(
someTask,
Completable.fromRunnable(() -> {
System.out.println("Done");
}).toObservable()
);
Update: Dealing with exceptions
Completable.fromRunnable internally catches exceptions from its Runnable and pushes them into the stream as onError emissions. However, if you are using Java, you have to deal with checked exceptions inside the run() method by yourself. To avoid that you could utilize Callable instead of Runnable, since its call() method's signature declares that it can throw exceptions. Completable.fromCallable() wraps exceptions into onError emissions as well:
Observable.concat(
someTask,
Completable.fromCallable(() -> {
System.out.println("Done");
return null;
}).toObservable()
);
Also Callable could be used to create an Observable or Single with a single item emission.
P.S. Check out the source code, these methods are pretty straightforward.
P.P.S. Kotlin has no checked exceptions ;)
Update 2
There is also fromAction factory method for creating Completable. It accepts Action objects.
A functional interface similar to Runnable but allows throwing a checked exception.
So the code could be simplified to:
Observable.concat(
someTask,
Completable.fromAction(() -> {
System.out.println("Done");
}).toObservable()
);
Related
I want to return an autocloseable object inside a CompletableFuture and use it in whenComplete without going to close it manually later.
This is the code that I've tried, but of course it won't work because it closes automatically when I return Jedis object. I haven't got any other ideas.
#Override
public CompletableFuture<Jedis> execute() {
if(!isServiceActive()) return CompletableFuture.completedFuture(null);
return CompletableFuture.supplyAsync(() -> {
try (Jedis jedis = pool.getResource()) {
return jedis;
} catch (RuntimeException e) {
logger.severe("Impossibile ottenere una nuova risorsa Jedis!", e);
throw new CompletionException(e);
}
}, executor);
}
In general, this is not possible; CompletableFuture is not designed for this. As you've noted, you can't close the resource before completing the future, because then it will be closed before any consumers get to act on it. That means the consumer will have to be responsible for closing the resource.
However, if your goal is to only need that Jedis instance in the one whenComplete call, then perhaps there is an alternative solution. Either modify execute() or create a new method that looks something like the following:
<T> CompletableFuture<T> execute(Function<? super Jedis, ? extends T> func) {
if (!isServiceActive()) return CompletableFuture.completedFuture(null);
return CompletableFuture.supplyAsync(() -> {
try (Jedis jedis = pool.getResource()) {
return func.apply(jedis);
} catch (Exception ex) {
// log exception
throw new CompletionException(ex);
}
}), executor);
}
The Jedis instance is closed by the time the future completes, but it still lets you do the needed work in the Function implementation. Using it would look like:
execute(jedis -> {
// use Jedis instance
return result;
})
.whenComplete((result, error) -> {
if (error != null) {
// process error
} else {
// process result
}
});
Though I don't know if your code can be modified to use this approach, as I notice your execute() method is an override (whether from a class/interface you control, I don't know). But even if you can't modify execute() directly or supply an overload feasibly, you might still be able to create a utility method that does something similar to the above.
So I'm using ListenableFuture as a return type for certain operations. I expect the users to add callback to the future and then handle the success and exception cases. Now if the user cannot handle the exception, I want to have the ability to throw that exception onto the main Thread. Here's some code example:
public class SomeProcessor {
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
public ListenableFuture<String> doStringProcessing() {
return executor.submit(() -> doWork());
}
private String doWork() {
return "stuff";
}
}
Then in a client class:
public class SomeConsumer {
public SomeConsumer (SomeProcessor processor) {
Futures.addCallback(processor.doStringProcessing(), new FutureCallback<String>() {
#Override
public void onSuccess(String result) {
// do something with result
}
#Override
public void onFailure(Throwable t) {
if (t instanceof ExceptionICanHandle) {
// great, deal with it
} else {
// HERE I want to throw on the Main thread, not on the executor's thread
// Assume somehow I can get a hold of the main thread object
mainThread.getUncaughtExceptionHandler().uncaughtException(mainThread, t);
// This above code seems wrong???
throw new RuntimeException("Won't work as this is not on the mainthread");
}
}
}, MoreExecutors.directionExecutor());
}
}
There is no direct way to do this.1
Hence, this question boils down to a combination of 2 simple things:
How do I communicate some data from a submitted task back to the code that is managing the pool itself? Which boils down to: How do I send data from one thread to another, and...
How do I throw an exception - which is trivial - throw x;.
In other words, you make the exception in your task, and do not throw it, instead, you store the object in a place the main thread can see it, and notify the main thread they need to go fetch it and throw it. Your main thread waits for this notification and upon receiving it, fetches it, and throws it.
A submitted task cannot simply 'ask' for its pool or the thread that manages it. However, that is easy enough to solve: Simply pass either the 'main thread' itself, or more likely some third object that serves as common communication line between them, to the task itself, so that task knows where to go.
Here is one simplistic approach based on the raw synchronization primitives baked into java itself:
public static void main(String[] args) {
// I am the main thread
// Fire up the executorservice here and submit tasks to it.
// then ordinarily you would let this thread end or sleep.
// instead...
ExecutorService service = ...;
AtomicReference<Throwable> err = new AtomicReference<>();
Runnable task = () -> doWork(err);
service.submit(task);
while (true) {
synchronized (err) {
Throwable t = err.get();
if (t != null) throw t;
err.wait();
}
}
}
public void doWork(AtomicReference<Throwable> envelope) {
try {
doActualWork();
catch (Throwable t) {
synchronized (envelope) {
envelope.set(t);
envelope.notifyAll();
}
}
}
There are many, many ways to send messages from one thread to another and the above is a rather finicky, primitive form. It'll do fine if you don't currently have any comms channels already available to you. But, if you already have e.g. a message queue service or the like you should probably use that instead here.
[1] Thread.stop(someThrowable) literally does this as per its own documentation. However, it doesn't work - it's not just deprecated, it has been axed entirely; calling it throws an UnsupportedOperationException on modern VMs (I think at this point 10 years worth of releases at least), and is marked deprecated with the rather ominous warning of This method is inherently unsafe. and a lot more to boot, it's not the right answer.
I am writing a Play2 application service method in Java that should do the following. Asynchronously call method A, and if that fails, asynchronously call method B.
To illustrate assume this interface for the backend called by the service:
public interface MyBackend {
CompletionStage<Object> tryWrite(Object foo);
CompletionStage<Object> tryCleanup(Object foo);
}
So in my service method, I want to return a Future that can complete with these:
Success of tryWrite completed
Fail of tryWrite and Success of tryCleanup completed and failing with exception of tryWrite()
(Note: Of course tryWrite() could do any cleanup itself, this is a simplified example to illustrate a problem)
The implementation of a service calling the backend like this seems difficult to me because the CompletionStage.exceptionally() method does not allow Composing.
Version 1:
public class MyServiceImpl {
public CompletionStage<Object> tryWriteWithCleanup(Object foo) {
CompletionStage<Object> writeFuture = myBackend.tryWrite(foo)
.exceptionally((throwable) -> {
CompletionStage<Object> cleanupFuture = myBackend.tryCleanup(foo);
throw new RuntimeException(throwable);
});
return writeFuture;
}
}
So version 1 calls tryCleanup(foo) in a non-blocking way, but the CompletionStage returned by tryWriteWithCleanup() will not wait for cleanupFuture to complete. How to change this code to return a future from the service that would also wait for completion of cleanupFuture?
Version 2:
public class MyServiceImpl {
public CompletionStage<Object> tryWriteWithCleanup(Object foo) {
final AtomicReference<Throwable> saveException = new AtomicReference<>();
CompletionStage<Object> writeFuture = myBackend
.tryWrite(foo)
.exceptionally(t -> {
saveException.set(t);
// continue with cleanup
return null;
})
.thenCompose((nil) -> {
// if no cleanup necessary, return
if (saveException.get() == null) {
return CompletableFuture.completedFuture(null);
}
return CompletionStage<Object> cleanupFuture = myBackend.tryCleanup(foo)
.exceptionally(cleanupError -> {
// log error
return null;
})
.thenRun(() -> {
throw saveException.get();
});
});
return writeFuture;
}
}
Version2 uses an external AtomicReference to store the failure, and makes the asynchronous second call in another thenCompose() block, if there was a failure.
All my other attempts to do so ended up so unwieldy that I don't want to paste them here.
Unfortunately CompletionStage/CompletableFuture does not provide exception handling API's with composition.
You can work around this though by relying on a handle() with a BiFunction that returns a CompletionStage. This will give you nested stages (CompletionStage<CompletionStage<Object>>) that you can the "unnest" using compose(identity()):
public CompletionStage<Object> tryWriteWithCleanup(Object foo) {
return myBackend.tryWrite(foo)
.handle((r, e) -> {
if (e != null) {
return myBackend.tryCleanup(foo)
.handle((r2, e2) -> {
// Make sure we always return the original exception
// but keep track of new exception if any,
// as if run in a finally block
if (e2 != null) {
e.addSuppressed(e2);
}
// wrapping in CompletionException behaves as if
// we threw the original exception
throw new CompletionException(e);
});
}
return CompletableFuture.completedFuture(r);
})
.thenCompose(Function.identity());
}
You may simply wait for the completion inside the handler:
public CompletionStage<Object> tryWriteWithCleanup(Object foo) {
return myBackend.tryWrite(foo).exceptionally(throwable -> {
myBackend.tryCleanup(foo).toCompletableFuture().join();
throw new CompletionException(throwable);
});
}
This will defer the completion of the result CompletionStage to the completion of the cleanup stage. Using CompletionException as wrapper will make the wrapping transparent to the caller.
However, it has some drawbacks. While the framework might utilize the thread while waiting or spawn a compensation thread, if it is a worker thread, the blocked thread might be the caller thread if the stage returned by tryWrite happens to be already completed when entering exceptionally. Unfortunately, there is no exceptionallyAsync method. You may use handleAsync instead, but it will complicate the code while still feeling like a kludge.
Further, exceptions thrown by the cleanup may shadow the original failure.
A cleaner solution may be a bit more involved:
public CompletionStage<Object> tryWriteWithCleanup(Object foo) {
CompletableFuture<Object> writeFuture = new CompletableFuture<>();
myBackend.tryWrite(foo).whenComplete((obj,throwable) -> {
if(throwable==null)
writeFuture.complete(obj);
else
myBackend.tryCleanup(foo).whenComplete((x,next) -> {
try {
if(next!=null) throwable.addSuppressed(next);
}
finally {
writeFuture.completeExceptionally(throwable);
}
});
});
return writeFuture;
}
This simply creates a CompletableFuture manually, allowing to control its completion, which will happen either directly by the action chained to tryWrite’s stage in the successful case, or by the action chained to the cleanup stage in the exceptional case. Note that the latter takes care about chaining a possible subsequent cleanup exception via addSuppressed.
The CompletableFuture API is fairly intimidating, lot's of accepts, and thens and other things; it's hard to tell why different options exist.
CompletableFuture<?> future = CompletableFuture.supplyAsync(() ->..., executor)
future.startNonBlocking...( (...) -> { callback behavior done when complete }
I'm basically trying to mimic a new Thread(() -> dostuff).start() but with better thread pooling, error handling, etc. Note: I don't actually need the Runnable interface here, I'm generifying a piece of existing code.
what's the right way to start my asynchronous task and execute behavior when it's complete? or handle an exception that is thrown?
Here's a simple async callback:
CompletableFuture.supplyAsync(() -> [result]).thenAccept(result -> [action]);
Or if you need error handling:
CompletableFuture.supplyAsync(() -> [result]).whenComplete((result, exception) -> {
if (exception != null) {
// handle exception
} else {
// handle result
}
});
new Thread(() -> dostuff).start()
means that dostuff implements Runnable, so you may use
static CompletableFuture<Void> runAsync(Runnable runnable)
static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
also.
This question already has answers here:
How can a Thread return a value after finishing its job?
(4 answers)
Closed 9 years ago.
I am wondering if there is a good way to return an object from a running thread.
In my android project (not important for the question) I have this method:
public void getFolders()
{
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
List<File> result = new ArrayList<File>();
Files.List request = null;
do
{
try
{
request = service.files().list();
request.setQ("'appdata' in parents");
FileList files = request.execute();
result.addAll(files.getItems());
request.setPageToken(files.getNextPageToken());
}
catch (IOException e)
{
System.out.println("An error occurred: " + e);
request.setPageToken(null);
}
}
while (request.getPageToken() != null && request.getPageToken().length() > 0);
}
});
t.start();
}
This method grabs some data from the internet and store the result in List<File> result. That's why I do not want to run it in the UI thread. Now I want to return this List to my main method. What is the best way to do this?
public interface Callable<V>
A task that returns a result and may throw an exception. Implementors define a single method with no arguments called call.
The Callable interface is similar to Runnable, in that both are designed for classes whose instances are potentially executed by another thread. A Runnable, however, does not return a result and cannot throw a checked exception.
How to use Callable.
EDIT:
Also you should be using AsyncTask in android for doing background tasks and not create threads of your own.
You should use Callable interface instead of Runnable interface to create threads. Callable interface offers a call() method, which can return an Object.
Because you cannot pass a Callable into a Thread to execute, you instead use the ExecutorService to execute the Callable object. The service accepts Callable objects to run by way of the submit() method:
<T> Future<T> submit(Callable<T> task)
As the method definition shows, submitting a Callable object to the ExecutorService returns a Future object. The get() method of Future will then block until the task is completed.
You can follow the sample on this link and customize it according to your requirement:
https://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6