How come Android's AsyncTask doesn't implement Future? - java

In Java, I've gotten used to working with Futures. Now I'm looking at Android, and AsyncTask implements almost all the same methods and covers similar lifecycles. But, if I want to be consistent and use Future all over my code, I have to wrap AsyncTask in a stupid wrapper, cause it doesn't actually implement Future.
All they'd need to add is an isDone() method, which seems like it would be trivial, then add implements Future<Result>. (added later: see my answer below for just how trivial it would be).
Any Android experts know some good reason / obscure bug it might cause why this hasn't been done?

From reading the actual code of AsyncTask.java it actually uses a Future task and then some more. A Future is a task that executes asynchronously on the go. An AsyncTask is scheduled on a queue for a single (or pool of) background thread(s).
An AsyncTask is actually more "superior" than a Future task. It does fancy scheduling and optimizations on top of Future's functionality. Just look at the API introduction levels. Future was introduced right from the start API 1.0. The AsyncTask object was introduced in API 3.
An AsyncTask has-a Future task, not is-a Future.
AsyncTask.java
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask<Result>(mWorker) {
#Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}

I'm still interested in the theoretical reasons "why" not to use AsyncTask for a Future.
But, for the record, I ended up creating my own little class (shown below). Just extend it instead of AsyncTask if you want a Future. IMO, a cleaner way than the #Eng.Fouad idea of accessing the private mFuture within the code. (But thanks for the idea, it got me looking into the source code a bit!) YMMV.
public abstract class FutureAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> implements Future<Result>{
#Override
public boolean isDone() {
return AsyncTask.Status.FINISHED == getStatus();
}
}

AsyncTask is too simple. It's intended for short tasks which may take a few seconds, but for which you don't want to lock up the UI thread. If you actually need a Future, your task is probably too complex for an AsyncTask anyway.
You can check the status of an AsyncTask by calling getStatus(). This will return an enum which can be one of Status.PENDING, Status.RUNNING or Status.FINISHED.

Related

Java Guava Framework on ListenableFuture

Is the below block of code valid? I saw this somewhere. But based on my own understanding, if we use immediateFuture to set the future to null upon construction.In theory, does the onSuccess code always execute, and it will never enter the onFailure block?
//public void doSomething(x,x){}
// doSomething(a,b)...
ListenableFuture<Void> future = Futures.immediateFuture(null);
Futures.addCallback(future, new FutureCallback<Void>(){
public void onSuccess(#Nullable Void aVoid){
//do something
}
public void onFailure(#Nonnull Throwable throwable){
//do something
}
return future;
}
First, your code as posted isn't valid. Just to start with, return future; belongs outside the callback definition. It is always easier to get help here if you copy-paste code samples that you know actually compile and demonstrate the behavior you're asking about.
Second, yes, in your scenario onSuccess() would always be called as soon as you add the callback.
I'm not clear what this is for, though. If you clarify what you're trying to do we can provide more useful help.

Releasing a resource provided by a Future

I'm creating an API that provides resources to the client which they will need to explicitly release (a la Closeable.close()) vi a Future. This pattern has a lot of nice features for our use case, but it comes with one wrinkle. If the client decides they no longer need the resource they can call Future.cancel(true) to cancel the (potentially expensive) allocation. However this introduces a race condition; if the resource finishes allocating before .cancel() is actually called then the future won’t actually free the resource.
Here’s an example:
Future<Resource> resource = service.requestResource();
try {
doSomething(resource.get(1, TimeUnit.MINUTES));
} catch (TimeoutException e) {
// by this point resource could be done, and .cancel() will be a no-op
resource.cancel(true);
}
It seems the "right" thing to do is for clients to always attempt to release the resource after calling cancel, e.g.:
if (!resource.cancel(true)) {
resource.get().close();
}
But this seems easy for a client to misuse. One option would be to use a ForwardingFuture and decorate .cancel() with this close-if-done behavior, but that seems like it would violate the contract that .cancel() "will fail if the task has already completed".
Must Future.cancel() no-op if the task is done? Is there a better pattern that resolves this race condition in a less error-prone manner? Or is this just something Future isn't designed to handle, and we should avoid using it?
Assuming you can expect your clients to at least call cancel just make it do the right thing by implementing it yourself:
public class CloseableFuture<V extends Closeable> extends FutureTask<V> {
#Override
public boolean cancel(boolean mayInterruptIfRunning) {
if (!super.cancel(true)) {
// Handle exception
get().close();
return false;
}
else {
return true;
}
}
}

AsyncTask equivalent in java

In android there is the AsyncTask which runs a thread and then i can use the method on post execute to interact with main thread again. is there an equivalent to this in java? i am trying to run a timer on separate thread (doInBackground) and once the time is finished it will then allow me to interact with the main theard to restart a service (onPostExecute will restart service)
I'm not Android developer but I think it could be easily implemented by using a CompletableFuture on Java 8:
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CompletableFuture;
import javax.swing.SwingUtilities;
public abstract class AsyncTask <Params, Progress, Result> {
protected AsyncTask() {
}
protected abstract void onPreExecute();
protected abstract Result doInBackground(Params... params) ;
protected abstract void onProgressUpdate(Progress... progress) ;
protected abstract void onPostExecute(Result result) ;
final void publishProgress(Progress... values) {
SwingUtilities.invokeLater(() -> this.onProgressUpdate(values) );
}
final AsyncTask<Params, Progress, Result> execute(Params... params) {
// Invoke pre execute
try {
SwingUtilities.invokeAndWait( this::onPreExecute );
} catch (InvocationTargetException|InterruptedException e){
e.printStackTrace();
}
// Invoke doInBackground
CompletableFuture<Result> cf = CompletableFuture.supplyAsync( () -> doInBackground(params) );
// Invoke post execute
cf.thenAccept(this::onPostExecute);
return this;
}
}
Solution Tailored for You
In short, look at java: run a function after a specific number of seconds.
For your purpose, you don't need an AsyncTask. AsyncTask is for running something that needs the time, but you would prefer it didn't (e.g. a complex calculation or fetching data from the internet). It's for getting around the problem that you would need to wait.
What you want to do instead is to introduce a delay, or more precisely you want to schedule some action to happen after a delay. You can use a class like AsyncTask for this as well, but it's an overkill and results in more complicated code. You should instead use a class which is tailored for delayed execution, which is Timer and TimerTask:
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
// your code here
}
},
5000
);
Equivalent of AsyncTask in standard Java
Note that AsyncTask is connected to a UI concept (UI = user interface), because it may only be started from the UI thread. It's not for generally running something asynchronously.
Thus, the best matching equivalent of android's AsyncTask is SwingWorker in Java. Swing is Java's standard UI framework. It has a similar concept as android with a UI thread. In Swing, this thread is called the Event Dispatch Thread. Hence, the design of SwingWorker is also very similar to AsyncTask. Even the doInBackground() method has the same name in both classes.
Asynchronous Execution in General
If your requirement is not related to a UI and you only want to source some time consuming operation out so it executes asynchronously, then you need to look at executors. There is a variety of different ways to use executors for many different purposes, so this would go beyond the scope of this answer. If you are interested in further information, start with Jakob Jenkov's tutorial on ExecutorService.

Can't call ASyncTask from another ASyncTask

I've looked at other questions and I failed to clarify my doubt as to call a task from another task, I have the following code:
protected List<Plan> doInBackground(String... params)
try {
JSONParsePlans parseJSON = new JSONParsePlans();
return parseJSON.execute(params[0], params[1], params[2]).get();
} catch (InterruptedException e) {
e.printStackTrace();
return null;
} catch (ExecutionExeption e) {
e.printStackTrace();
return null;
}
}
parseJSON is a task, when I run the program does nothing, not even called to task, it's like what Android omitted for security.
According to this StackOverflow Post:
but only inside onProgressUpdate() or onPostExecute() since these methods runs on the UI thread. Therefore, start the second AsyncTask on the UI thread by choosing one of the two methods listed above.
So you can call an AsyncTask from another AsyncTask, so long as it runs in either of those two methods.
There is also another StackOverflow post that addresses this issue here
It is possible to call an Async Task from another Async Task
but only inside onProgressUpdate() or onPostExecute()
Reason - since these methods runs on the UI thread. Therefore, start the second AsyncTask on the UI thread by choosing one of the two methods listed above.

How to handle Java futures with Akka actors

I have a layered architecture in a Java web application. The UI layer is just Java, services are typed Akka actors and external service calls (WS, DB etc.) are wrapped in Hystrix commands.
THe UI calls the service and the service returns an Akka future. It's an Akka future because I want to make UI coding simpler with the onComplete and onFailure callbacks that Akka futures provide. The service then creates the future that does some mapping etc. and wraps a call to a HystrixCommand that returns a Java future.
So in pseudocode:
UI
AkkaFuture future = service.getSomeData();
Service
public AkkaFuture getSomeData() {
return future {
JavaFuture future = new HystrixCommand(mapSomeData()).queue()
//what to do here, currently just return future.get()
}
}
The problem is that I would like to free up the thread the service actor is using and just tie up the threads that Hystrix uses. But the java future prevents that because I have to block on it's completion. The only option I can think of (which I'm not sure I like) is to poll the Java future(s) constantly and complete the Akka future when the Java future finishes.
Note: the question isn't really related to Hystrix per se, but I decided to mention it if somebody comes up with a solution specifically related to Hystrix.
I'm marking the answer by #Hbf as a solution, since I ended up doing an Akka poller as explained in How do I wrap a java.util.concurrent.Future in an Akka Future?. For reference I also tried:
Creating a HystrixCommandExcutionHook and extending HystrixCommand to allow callbacks. That didn't work because the hook wasn't called at the right time.
Using Guavas listenable future by having a decorated executor create the futures inside Hystrix and then casting the futures from the commands. Doesn't work because Hystrix uses a ThreadPoolExecutor which can't be decorated.
EDIT: I'm adding the Akka poller code below, since the original answer was in Scala and it hangs if the Java future doesn't cancel nicely. The solution below always walks away from threads after a timeout.
protected Future wrapJavaFutureInAkkaFuture(final java.util.concurrent.Future javaFuture, final Option maybeTimeout, final ActorSystem actorSystem) {
final Promise promise = Futures.promise();
if (maybeTimeout.isDefined()) {
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, Option.option(maybeTimeout.get().fromNow()), actorSystem);
} else {
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, Option. none(), actorSystem);
}
return promise.future();
}
protected void pollJavaFutureUntilDoneOrCancelled(final java.util.concurrent.Future javaFuture, final Promise promise, final Option maybeTimeout, final ActorSystem actorSystem) {
if (maybeTimeout.isDefined() && maybeTimeout.get().isOverdue()) {
// on timeouts, try to cancel the Java future and simply walk away
javaFuture.cancel(true);
promise.failure(new ExecutionException(new TimeoutException("Future timed out after " + maybeTimeout.get())));
} else if (javaFuture.isDone()) {
try {
promise.success(javaFuture.get());
} catch (final Exception e) {
promise.failure(e);
}
} else {
actorSystem.scheduler().scheduleOnce(Duration.create(50, TimeUnit.MILLISECONDS), new Runnable() {
#Override
public void run() {
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, maybeTimeout, actorSystem);
}
}, actorSystem.dispatcher());
}
}
Java futures are known to be inferior in design compared to something like Scala futures. Take a look at the discussion "How do I wrap a java.util.concurrent.Future in an Akka Future", for example.
But: Maybe, instead of polling (as suggested in the above discussion), Hystrix offers some kind of onComplete callback? I do not know the library at all but stumbled upon an onComplete in the Hystrix API. Maybe it helps?
As of Hystrix 1.3 it now also supports true non-blocking callbacks and that will fit much better into Akka/Scala Future behavior that is non-blocking and composable: https://github.com/Netflix/Hystrix/wiki/How-To-Use#wiki-Reactive-Execution

Categories

Resources