Waiting for threadpool to complete execution - java

I am new to threading . I have searched many questions related to my problem but I am not able to find the right solution for me. What I am doing is I am using four async tasks to fetch data from four different social media using the THREAD_POOL_EXECUTOR.
code is as follows.
new Fb().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new Twitter().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
...
mAdapter = new MyAdapter(getActivity(),
(ArrayList<Model>) showList);
mListView.setAdapter(mAdapter);
I want the calls to be in parallel to save the time of fetching data. Now the idea is that i want all the four threads to complete the work and after that I want to display the sorted data as per timestamp. Right now the problem is that my setAdapter get called before the four threads complete fetching data as adapter is set on the UI thread. I want a mechanism to block the UI thread until all four threads complete fetching the data.
I have found that maybe I can use the shutDown() and awaitTermination() methods of ExecutorService . It would be great if anyone can help me in anyway. Thanks a lot

What I would do is:
Create an empty ArrayList in your activity
Pass this arrayList to your adapter and set the adapter on your ListView. setAdapter method will not affect the listView - it will still be empty becase the list is empty.
Start 4 AsyncTasks and fetch data. In onPostExecute() add this data to the ArrayList and invoke notifyDatasetChanged() on the adapter.
You should never block an UI thread because it is just wrong. When you want all data to be shown at once you can make a simple counter, make counter++ in every onPostExecute and invoke notifyDatasetChange() only when counter is 4.

Invoke method shutdown() from ExecutorService.
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html

If you're really okay with blocking the UI thread, try this:
new Fb().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new Twitter().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
...
AsyncTask.THREAD_POOL_EXECUTOR.shutdown();
while (!AsyncTask.THREAD_POOL_EXECUTOR.isTerminated()) {}
mAdapter = new MyAdapter(getActivity(),
(ArrayList<Model>) showList);
mListView.setAdapter(mAdapter);
In most cases though, blocking the UI thread isn't a good idea.

I could successfully handle the problem without going deeo into threading. I used the simple concept of making booleans true after execution of each thread. And in the UI thread I checked for infinte time i.e
while(true)
{
if(flag1 && flag2 && flag3 && flag4)
{
//set the adapter and make the flags false
break;
}
}
Dont forget to make the falgs false otherwise execution will go on for indefinite time.

Related

How to create a thread that listens for a state change?

I was spending my entire morning figuring out how Android threads and locks work. I have read about Thread, Runnable, Handler, AsyncTask, Executors, HandlerThread, ThreadPoolExecutor, and so on. I have also read about Condition, Lock and the method synchronize. But, I am still hesitant about what type of thread should I use in my application.
Summarizing and simplifying, my app should do the following:
A working thread will be attached to a specific Fragment, which displays a GridLayout with different elements. That thread should generate random numbers that corresponds with each one of the grid elements and send them sequentially to the parent Fragment, which will hide them a fixed number of milliseconds. However, the thread should be able to pause itself when user clicks a button in the Fragment (requiring a kind of synchronized usage).
The questions are the following:
What kind of Android thread is the most optimal in my case?
What is the best way to listen for a change in the state inside the thread loop if a user want to pause it?
For now, I am considering to extend the raw Thread class and use synchronize() to check the state, but I feel that it is not the most appropiate way to achieve this.
Thanks in advance.
I think RxJava would be a good fit for this problem. I'm away from my IDE, but I envisage something where you:
Create a "Timer", with a random interval, for each individual item (say a GridItemViewModel) in your grid layout, and have it emit that item when it finishes.
Combine all those timers into a List.
Run all the timers simultaneously.
When each individual timer finishes, it emits its "item" (i.e. ViewModel). Use that to hide the appropriate item in your UI
When all items finish, it will trigger onComplete() in your overall Observable. When this is called, you know all tasks have fininshed.
So...
final List<Observable<Item>> tasks = gridItems()
.stream()
.map(item -> {
final int seconds = ThreadLocalRandom.current().next(0, 5);
return Observable.timer(seconds, TimeUnits.SECONDS).map(ignore -> item);
})
.collect(Collectors.toList());
Observable.merge(tasks)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(item -> {
//One item has completed. Take the "item" value
// and use it to update your UI.
}, t -> { /*No error handling*/}, () -> /*All items finished*/);

Handling loading states of multiple threads in Activity

In my Android app i'd like the user to be able to see when a task is running in the background.
These tasks can be either network calls or database operations, running on separate background threads.
There is a single indeterminate ProgressBar in the Activity, which i would like to show if any background tasks are running, and hide it otherwise.
I've searched for solutions to this and people seem to use LiveData for similar purposes.
So i figured i'd create a LiveData in the ViewModel of the Activity that represents the current loading state of the app, something like this:
val loadingState = MutableLiveData<State>()
Whenever i'm starting or finishing a task, i'd post the appropriate value to this LiveData:
// starting background operation
loadingState.postValue(Status.LOADING)
And i'd observe on it from the Activity and show/hide the ProgressBar according to the current state:
loadingState.observe(this, Observer { status ->
when (status) {
Status.LOADING -> showProgressBar()
Status.IDLE -> hideProgressBar()
}
}
My problem is i don't know how to handle this when there are multiple tasks running on multiple threads.
For example:
A task starts and sets the status to LOADING (correct)
B task starts (the status is already LOADING so nothing happens) (correct)
A task finishes and sets the status to IDLE, however B is still running (wrong)
The ProgressBar will be hidden even though B is still in progress
B task finishes, but the status is already IDLE (wrong)
I thought i could maintain a Collection of LiveData objects (as in a separate LiveData for each task) but it seems really cumbersome.
Is there an idiomatic way to handle this?
(Java answers are welcome as well)
i have a simple idea
in the view model use variable like that
var numberOFThreads = 0
and replace this line
loadingState.postValue(Status.LOADING)
with
if(numberOFThreads == 0){
loadingState.postValue(Status.LOADING)
}else{
numberOFThreads++
}
and
if(numberOFThreads == 0){
loadingState.postValue(Status.IDLE )
}else{
numberOFThreads--
}

Get all AsyncTasks that are executed and currently running in Android app

I have a number of AsyncTask instances that are downloading some different content from the server. They run on executor:
final GetStationsTask getStationsTask = new GetStationsTask();
getStationsTask
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, URL_STATIONS);
Currently I have 3 subclasses of AsyncTask, but this number will not stay the same. I am also implementing some kind of retrying for tasks that were not completed for different reasons, and I would like to download everything from the beginning, if at least one of the tasks was not finished correctly (the data was not received):
// mHandler = new Handler(); // an instance variable
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if (!allDataSet()) {
// here I want to cancel the tasks that are still running
// and rerun all of them
}
}
}, 30000); // I give all the tasks 30 seconds to complete
For that I suppose I need to know which tasks are currently running, which tasks have finished correctly and which ones were cancelled, because if all the tasks get restarted, I need to cancel the running ones first to prevent the data from being received multiple times. Any ideas how to solve it?
Override the base AsyncTask, and use that as your base class for all AsyncTasks. Have the overriden task have a static list of running, cancelled and finished tasks. Then add each task to the relevant list in the base class methods.
You can keep a list of AsyncTasks being currently executed in some singleton class, ie. Application extended one.:
List<AsyncTask<String, String, String>> downloadsAsycs = new ArrayList<AsyncTask<String, String, String>>();
inside of your asynctask's onPostExecute remove it from list using downloadsAsycs.remove(this). Remember to either synchronize on using this list, or always modify/read it on UI thread, ie. inside Handler from mainlooper or in onPreExecute/onPostExecute. You can check status of your async task using AsyncTask.getStatus(). After a while it starts getting complicated.
You could also switch from AsyncTask to Executors.newFixedThreadPool and ExecutorService.invokeAll. You could invoke all your tasks and have returned Future for all of them which allow to control them. You could even use Future.get with timeout on some back thread (even asynctask.doInBackground) to 30s, and after this time use Future.cancel if operation timed out.
Since the number of tasks is unknown, but they need to communicate in some way.
I would suggest to create 2 classes:
YourTask class - all needed tasks would be it's instances
TaskMediator - which manage communication as Mediator Design Pattern
So every time one task (YourTask) created it register it's self
to predefined class (TaskMediator) which manage their communication.
That way you get looser coupling between their objects,
but still keeps one communication channel
*By the way your TaskMediator can be Singleton as suggested by Marcin Jedrzejewski

How to listen new db records through java

Currently I use while(true) and Thread.sleep() for checking for new records in the db and execute java code.
Here is an example:
public class StartCommands implements Runnable{
private Active_Job activeJob;
Runnable execute_command;
public StartCommands(){
activeJobs = new Active_Job();
}
#Override
public void run(){
int jobId = 0;
while(true){
//access the db and get one row from the table by the status
jobId = activeJobs.get(Status.NEW);
if (jobId > 0){
activeJob.updateStatus(Status.INIT);
execute_command = activeJob.getCommand();
new Thread(execute_command).start();
activeJob = new Active_Job();
jobId = 0;
}
Thread.sleep(10*1000);
}
}
}
I've few places in the code that I use this method. But I dont like the endless loop and check every 10 seconds for new row.
So what I'm looking for is some kind of listener: once new record has been entered - execute java code. Some of the inserts executed from the application and some are not.
The technique you are using is called polling. You are checking for new records, waiting a set amount of time, then checking again for new records. One good way to respond to new records might be to create a controller that handles inserting new records into the database and force all clients (who update database records) to use the controller to do so. Then the controller can alert you when there is a new record. To facilitate the controller's alerts, you can set up a web service where the controller can contact you.
I say that this "might" be a good way to do it because creating a controller and a web service is obviously extra work. However, it would make polling unnecessary. If you want to continue using your polling technique, you could make a service (producer) that does the polling and fills a queue with the new results. Your other program (consumer) can then retrieve items from the queue and do something with them.
There is no builtin "update listener" in MySQL (or any SQL database I'm aware of), so you have to build your own.
Notice that in your implementation, if two new rows are added you will handle one, wait 10 seconds, then handle the next one. Your code cannot handle more than one event every 10 seconds.
What you want to do is separate the polling of the database from the dispatching of the worker threads. Have the polling loop wake up every n seconds, read ALL new records from the database, and add them to a work queue. Have a consumer thread that is waiting on the queue and launches processors as messages appear on the queue. using a thread pool implementation.
#nir, Since there is no mysql database update listener in java so far, so what you can do is, create a database update trigger against the table, the change of which you want to listen. Within the trigger statement or code construct a function.Now from within that function call java function. Java function should be such that it modify some text, say "a". Now register the listener against the change in "a". And within the class implementing the text change listener of "a",put the code you want to execute.
The Condition Interface would work nicely for your needs. It will give you the granular control you are looking for, and it will avoid the problem of spinning the thread constantly.
http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html
Use a trigger, call a User Defined Function that uses sys_exec() to run an external app that signals an inter-process semaphore. Your listener thread can wait on that and, when signaled, process the new records.
In oracle exists something called database change notification http://docs.oracle.com/cd/E11882_01/java.112/e16548/dbchgnf.htm and I just implement a component like yours is there something like that in mysql or what approach you arrived?

Android - How to update ArrayAdapter Asynchronously?

I'm using an AsyncTask class to add, remove and clear items from my ArrayAdapter. Unfortunately, when any of those tasks are run, the ArrayAdapter wants to notifyDataSetChanged(), which requires that the thread be run on the uiThread.
If I use runOnUiThread(new Runnable(){...}); in order to update an ArrayAdapter Asynchronously, doesn't that defeat the purpose of trying to update it in a new Thread to begin with?
What is the best approach here?
Do .notifyDataSetChanged() insde onPostExecute() method. onPostExecute() method runs on Ui-Thread. If your app requires to periodically update during execution of doInBackground() method then use publishProgress() (which will envoke onProgressUpdate() method) and call notifyDataSetChanged() inside onProgressUpdate() method, which also runs on Ui-thread.
Just to add something to what everyone else already said, after your task is done running, you might want to set the adapter (or a new one) again for the view you are working with.
AFAIK depending on your code, after notifyDataSetChanged or after refreshing the cursor, the view might not update right away if you are not working with a reference.
If you leave your activity and when you come back, the view is updated, you probably need to set the adapter again.
To answer your first question, calling runOnUiThread doesn't defeat the purpose as long as the only thing you call on the UI thread is notifyDataSetChanged(). Do all your actual, potential long running, tasks in the AsycnAdpater and then when you're ready to tell the activity things have changed, call runOnUiThread(). It will only run the commands you specify in the Runnable you pass to it.
That said, why not instead of using an AsyncTask, try using an AsyncTaskLoader. AsycnTaskLoaders were designed almost specifically for populating lists asynchronously. They weren't introduced until API level 10, but you can still access them from older API levels by using the android Support Package.

Categories

Resources