Android: Future/FutureTask for parallel processing of data - android

I am trying to optimize a complex data updater and parser for my Android app. The server provides three interface functions. The parser requires the data from all those three functions.
When the download of the data is finished, the parser can start. It consists of many different independent tasks which can be parallelized.
I was thinking of using Futures or FutureTasks for processing the data.
So basically, this is the procedure:
create Task-1, Task-2, Task-3 for downloading the data
wait for the downloads to be finished
create Task-1,..., Task-N for parsing the data
wait for the parser to be finished
call a callback to signal that process is done.
My first question: is it possible to create Futures with asynchronous functions, which use callbacks to return the data (network framework)?
Second question: are there any drawbacks in using Futures or FutureTasks respectively in this scenario or are there any better solutions to achieve that?
Thank you.

Basically you are Trying to achieve the following.
Step 1 - User from UI starts 1,2,... n download tasks.
Step 2 - Once each of the task is completed, new thread should be started to process it.
Step 3 - Once all n Tasks are completed, UI should be updated ... may be with a success dialog.
This can be achieved easily by using Async Task. I am going to tell you the approach and not the code sample.
Things to note about Async Task
Before 1.6, Async Task handles all background operations with a single additional thread.
After 1.6 till 3.0 .. it was changed, so that a pool of thread had begun to be used. And operations could be processed simultaneously.
Since Honeycomb default behavior is switched back to use of a single worker thread (one by one processing).
How to implement your requirement
For your requirement, you can use the method (executeOnExecutor) to run simultaneous tasks (1 till n tasks) if you wish (there two different standard executors: SERIAL_EXECUTOR and THREAD_POOL_EXECUTOR).
The way how tasks are enqueued also depends on what executor you use. In case of a parallel one you are restricted with a limit of 10 (new LinkedBlockingQueue(10)). In case of a serial one you are not limited (new ArrayDeque()).
So the way your tasks are processed depends on how you run them and what SDK version you run them on. As for thread limits, we are not guaranteed with any, yet looking at the ICS source code we can say that number of threads in the pool can vary in range 5..128.
When you start too many tasks (like 100s or more) with default execute method serial executor is used. Since tasks that cannot be processed immediately are enqueued you get OutOfMemoryError (thousands of tasks are added to the array backed queue).
Exact number of tasks you can start at once depends on the memory class of the device you are running on and, again, on executor you use.
So by following this approach, once all the tasks are completed, you can use a handler to update the UI.
Hope this helps.

Related

Android multithreading - How can I customize consuming Runnables in a BlockingQueue?

I'm currently learning Android programming and I'm doing my first application using VS 2017 in C# (Xamarin). Right now I'm trying to understand how to split a complex computation into several threads - more accurately, the features I should look into.
Now, what I want to do is to iterate over all possible values of an unsigned int and perform some computation on it. It's a search, so some of those numbers will be of interest and I need the threads to update a progress bar and some view containing any results found so far. The complexity here is the huge number of operations that will be performed.
I've looked into Async Tasks, Thread Pool Executor, Thread Factory, Blocking Queues and Runnables. So I'm thinking a Thread Pool sounds like the way to go, especially by specifying how many processors are available and how many threads can be used.
Going by this SO question/answer, I would use an Async Task for a short operation and Java threads for more complex operations. So, despite using C# Xamarin, I guess I'm looking into Javal.Util.Concurrent.Thread's..
My goal with all this, is to allow the user to start this complex task and pause it at any point, or abort, as well as save the search state at any point to resume later. To do this, I want to subdivide this search on all possible uint values into multiple tasks - perhaps thousands of small tasks that could be executed by worker threads. For the pause feature, I was thinking the example in Android's documentation, that I previously linked, which implements Pause/Resume methods in a custom Thread Pool Executor. The save/store should be easy.. if my tasks are ordered all I need is to keep track of the last value tested and fruitful values.
I've setup a custom Thread Pool Executor, Factory and Runnables. However, I am quite confused as to how to do two things:
How exactly should I add runnables to the queue? And from which thread?
How, and where, do I know when the search was completed? What happens to the minimum number of threads in the Thread Pool Executor when the job is completed? I want to destroy all the threads when it's over.
In my operations I could have thousands of tasks. In fact, I can decide between 4096 large tasks, or 65536 smaller tasks. They can be identified by a range of uints to be checked, or a single uint index. But either way I know ahead of time how many they are and I think it would be more efficient if I didn't have to create that many runnables... Is there a way I can customize how the threads will pick up their next work from the Queue?
Or perhaps the Thread Pool Executor is just not the right tool for what I'm trying to achieve here?
I'm mostly looking for some insight on the multithreading tools available in Android and how can I go about implementing a proper solution for my problem.
You should definitely have a look to reactive programming http://reactivex.io/ and https://github.com/ReactiveX/RxJava
This is the best and cleanest way to execute tasks in background, for example you could do :
myObservable
.subscribeOn( Schedulers.io() ) // Thread where you execute your code
.observeOn( AndroidSchedulers.mainThread()) / Thread where you get result
.subscribe(...)

How to use RxJava for asynchronously executing a dynamic list of consecutive dependent operations?

I'm working on an Android Service Library (AAR) that has to execute a variable number of processes consecutive/pipelined on an input (JSON) in the background.
Thereby, the next process takes the output of the previous process as input.
The processes can involve literally every kind of possibly long running tasks (http requests, IO/DB requests, heavy data crunching, ...)
It shall be possible to log the progress between every process and get the final output of the last process e.g. in a subscriber (library service thread).
The processes should run stable, in case internet connection is lost or parent application state is changing.
I'm currently using Robospice in my library to achieve stability for multiple requests...
This question: How to implement a sequence of consecutive operations using rxjava
is related to my question, except I ask for a variable sequence of operations.
Is it possible achieve this with Rxjava? If yes, how? If not, what are other options?
My idea how to do it somehow without Rxjava:
Keep Process count for every request
Processes[counter].execute(result, callback)
Callback-OnSuccess(result): increase process counter and start Processes[counter] with result
But I'm not experienced with thread handling and think this is not very robust and maybe it doesn't even work or blocks the calling thread (what makes the library not usable for this time)

Multiple AsyncTask vs multiple requests within one AsyncTask

I'm following this tutorial to create an XML reader with options to download multiple feeds at once. Are there any downsides to executing multiple AsyncTasks (max 3) simultaneously? I'm going to add a timer to check if they finished.
Running multiple AsyncTasks at the same time -- not possible? It is possible. However it could be, that due to the cpu depending on each device, one is faster than the other. But as #Alex already answered, you wont get "real" multitasking. Haven't it tried yet I would assume, that doing it all in one AsyncTask is faster. And you could reuse the connection you established to the server.
For better architecture I'll choose 1 AsyncTask per request. It is easier to manage actual request. Also it would be easier to modify (add/remove request).
Downsides of executing multiple AsyncTasks depend on your knowledge of AsyncTask lifecycle. You need to execute it correctly (depends on android version).
Good article about the dark side of Async tasks http://bon-app-etit.blogspot.com.by/2013/04/the-dark-side-of-asynctask.html
They won't be run simultaneously, but serially. See here:
When first introduced, AsyncTasks were executed serially on a single
background thread. Starting with DONUT, this was changed to a pool of
threads allowing multiple tasks to operate in parallel. Starting with
HONEYCOMB, tasks are executed on a single thread to avoid common
application errors caused by parallel execution.
If you truly want parallel execution, you can invoke
executeOnExecutor(java.util.concurrent.Executor, Object[]) with
THREAD_POOL_EXECUTOR

asynctask doInBackgound() not running if there's a asynctask already running

When the user logs in into my app. I am starting an asynctask to maintain the user session. And that async task is running indefinitely till the user logs out. My problem is that when I try to start other asynctasks, their doInBackground() method is never executed.
I read somewhere that if an async task is already running, we cannot start new async task. I can confirm this because when i removed the user session async task, it worked properly. Is there a workaround?
P.S.: I have already used executeOnExecutor() method. but it didn't help.
For potentially long running operations I suggest you to use Service rather than asynctask.
Start the service when the user logs in
Intent i= new Intent(context, YourService.class);
i.putExtra("KEY1", "Value to be used by the service");
context.startService(i);
And stop the service when the user logs out
stopService(new Intent(this,YourService.class));
To get to know more about Service you can refer this
Service : Android developers
Service : Vogella
To know more about asynctask vs service you can refer this
Android: AsyncTask vs Service
When to use a Service or AsyncTask or Handler?
I read somewhere that if an async task is already running, we cannot start new async task.
Yes,That is fact that you can't run more then 5 (five) AsyncTaskat same time below the API 11 but for more yes you can using executeOnExecutor.
AsyncTask uses a thread pool pattern for running the stuff from doInBackground(). The issue is initially (in early Android OS versions) the pool size was just 1, meaning no parallel computations for a bunch of AsyncTasks. But later they fixed that and now the size is 5, so at most 5 AsyncTasks can run simultaneously.
I have figure out Some Threading rules and i found one major rule is below ,
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
What is definition of AsyncTask?
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
How & Where use it?
AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended to use it.
Why you can't use multiple AsyncTask at same time ?
There are a few threading rules that must be followed for this class to work properly:
The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN.
The task instance must be created on the UI thread.
execute(Params...) must be invoked on the UI thread.
Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Running multiple AsyncTasks at the same time — not possible?
Test sample of parallel excution of AsyncTasks
Try Executor
You should go with Executor that will mange your multiple thread parallel.
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
...
Sample Example 1
Sample Example 2
Just like a few others here, I object to the premise of the question.
Your core problem is that you are using an AsyncTask to perform a task beyond its scope. Others have noted this too. Those who offer solutions that can mitigate your problem through low-level threads (even java.util.Concurrent is low-level which is why Scala uses Akka actors as an abstraction), Service, etc. are quite clever, but they are treating the symptom rather than curing the disease.
As for what you should be doing, you are not the first to want to maintain a user session in an Android application. This is a solved problem. The common thread (no pun intended) in these solutions is the use of SharedPreferences. Here is a straightforward example of doing this. This Stack Overflow user combines SharedPreferences with OAuth to do something more sophisticated.
It is common in software development to solve problems by preventing them from happening in the first place. I think you can solve the problem of running simultaneous AsyncTasks by not running simultaneous AsyncTasks. User session management is simply not what an AsyncTask is for.
If you are developing for API 11 or higher, you can use AsyncTask.executeOnExecutor() allowing for multiple AsyncTasks to be run at once.
http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor(java.util.concurrent.Executor, Params...)
I'll share with you, what we do on our App.
To keep user Session (We use OAuth with access/refresh tokens), we create a Singleton in our Application extended class. Why we declare this Singleton inside the MainApplication class? (Thats the name of our class), because your Singleton's life will be tided to the Activity that has created it, so if your Application is running on low memory and Garbage Collector collects your paused Activities, it will release your Singleton instance because it's associated to that Activity.
Creating it inside your Application class will let it live inside your RAM as long as the user keeps using your app.
Then, to persists that session cross application uses, we save the credentials inside SharedPreferences encrypting the fields.
yes starting 2 or more asynctasks simultaneously may cause issues on some devices. i had experienced this issue few months back. i could not predict when the 2nd asyncTask would fail to run. The issue was intermittent may caused by usage of memory as i was executing ndk code in asynctask. but i remember well that it depended on memory of device.
Similar question had been asked before. I would post the link for the similar question.
AsyncTask.executeOnExecutor() before API Level 11
Some users suggest go for Service. My advice is don't go for that path yet. Using service is much more complicated. Even you are using service, you still have to deal with threading, as
Note that services, like other application objects, run in the main
thread of their hosting process. This means that, if your service is
going to do any CPU intensive (such as MP3 playback) or blocking (such
as networking) operations, it should spawn its own thread in which to
do that work....
If we can solve a problem in elegant way, don't go for the complicated way.
I would suggest that, try one of the APIs in java.util.concurrent as suggested in below
AsyncTask is designed to be a helper class around Thread and Handler
and does not constitute a generic threading framework. AsyncTasks
should ideally be used for short operations (a few seconds at the
most.) If you need to keep threads running for long periods of time,
it is highly recommended you use the various APIs provided by the
java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and
FutureTask.
I can't give you any code example so far, as I do not know how you design your session managing mechanism.
If you think your long running session managing task shouldn't bind to the life cycle of your main application life cycle, then only you might want to consider Service. However, bear in mind that, communication among your main application and Service is much more cumbersome and complicated.
For more details, please refer to http://developer.android.com/guide/components/services.html, under section Should you use a service or a thread?

How to execute parallel REST API calls in android

Hi I am developing android application. My application contains REST API calls for fetching data from server. So my application requirements are like this:
consider I have 2 REST API calls all are independent; That mean both are not dependent on each other; So I want parallel execution. Result of both API calls associated with two different activities.
I want to run both network calls in background. Don't want to execute on UI thread.
I am confuse with following few solutions:
use separate async task for each network call. What happen if I execute 10 calls parallel with async task?
Use intent service: Will intent service is good solution for handling multiple network calls parallel in background.
How to handle this in proper way. Need good solution for this. Need help. Thank you.
Executing on 2 AsyncTasks will work. However, on Android versions 3.0 or higher you need to call task.executeOnExecutor(THREAD_POOL_EXECUTOR, params) instead of execute. If you don't do that, the 3.0 implementation of AsyncTask only runs 1 task at a time serially. If you do this it uses a pool of about 5 threads to run them.

Categories

Resources