At application launch time I am making network call (resttemplate Get call) to fetch data.
Scenario is something like this,
1)Parent call which returns list of tokens(Id's)
2)Once I got list of tokens(Id's),I iterate through it make network call for each token(Id) to get Data.
What I have done so for:
1)I have used Intent service to make parent network call to get list tokens(ID's).
2)Once I got list token(Id's) I started my AsyncTask executeOnExecutor,Passing list of tokens(ID's) to asynctask through constructor and starting AsyncTask executor.
Something like this,
MyAsyncExecutorTask executorTask = new MyAsyncExecutorTask(List<Integer> of tokens);
executorTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,(Void[]) null);
And In MyAsyncExecutorTask this is what I am doing.
protected Void doInBackground(Void...params) {
//Settimg max priority
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
for (int i = 0; i < scheduleList.size(); i++) {
ScheduleImpl scheduleImpl = new ScheduleImpl();
//Making network call to get data using token
scheduleImpl.getData(scheduleList(i));
}
}
Its working as it should be.
My doubts or Questions are:
1)Am I using Async executeOnExecuter() in right way(I want to make parallel network calls).I don't see any huge performance improvement after switching from AsyncTask execute() to Async executeOnExecuter().
2)How to check how many number worker threads running.
You can make it like this:
AsyncTaskGetTokens.java
public class AsyncTaskGetTokens extends AsyncTask<Void,Integer, List<Integer>> {
private ProgressDialog pd;
private Context context;
private String dataURL;
public AsyncTaskGetTokens (Context context, Integer token)
{
this.act = act;
this.token = token;
}
protected void onPreExecute()
{
this.pd = ProgressDialog.show(context, "", "");
}
protected Integer doInBackground(Void... arg0) {
List<Integer> tokenList = new List<Integer>();
//get token list from URL here
return tokenList;
}
protected void onPostExecute(List<Integer> tokenList)
{
this.pd.dismiss();
AsyncTaskGetData.tokensDownloading = new List<AsyncTaskGetData>();
foreach(Integer token : tokenList)
{
AsyncTaskGetData.tokensDownloading.add(new AsyncTaskGetData(context, token); // here you create a list with all the tokens that will be downloaded
}
foreach(AsyncTaskGetData asynctask : AsyncTaskGetData.tokensDownloading)
{
asynctask.execute(); // here you will start downloading the data from each token
}
}
}
AsyncTaskGetData.java
public class AsyncTaskGetData extends AsyncTask<Void,Integer, Data> {
public static List<AsyncTaskGetData> tokensDownloading;
private ProgressDialog pd;
private Context context;
private Integer token;
public AsyncTaskGetData (Context context, Integer token)
{
this.context = context;
this.token = token;
}
protected void onPreExecute()
{
this.pd = ProgressDialog.show(context, "", "");
}
protected Data doInBackground(Void... arg0) {
Data data = getDataFromURL(token);
return data;
}
protected void onPostExecute(Data data)
{
//show data here
this.pd.dismiss();
}
}
1)Am I using Async executeOnExecuter() in right way(I want to make parallel network calls).I don't see any huge performance improvement after switching from AsyncTask execute() to Async executeOnExecuter().
From Android Documentation
execute:
Executes the task with the specified parameters. The task returns itself (this) so that the caller can keep a reference to it.
Note: this function schedules the task on a queue for a single background thread or pool of threads depending on the platform version. 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 HONEYCOMB, tasks are back to being executed on a single thread to avoid common application errors caused by parallel execution
executeOnExecuter
Executes the task with the specified parameters. The task returns itself (this) so that the caller can keep a reference to it.
This method is typically used with THREAD_POOL_EXECUTOR to allow multiple tasks to run in parallel on a pool of threads managed by AsyncTask, however you can also use your own Executor for custom behavior.
Warning: Allowing multiple tasks to run in parallel from a thread pool is generally not what one wants, because the order of their operation is not defined. For example, if these tasks are used to modify any state in common (such as writing a file due to a button click), there are no guarantees on the order of the modifications. Without careful work it is possible in rare cases for the newer version of the data to be over-written by an older one, leading to obscure data loss and stability issues. Such changes are best executed in serial; to guarantee such work is serialized regardless of platform version you can use this function with SERIAL_EXECUTOR.
The question isn't about the performance improvement necessarily. When you run as executeOnExecuter, there is no guarantee that the calls will return in the order you made them. An execute method will schedule the task in a queue for a single background thread.
2)How to check how many number worker threads running.
You have the ability to define your own work queue, so if the question is how many threads can you run, then refer to this post Android AsyncTask threads limits?
I'm not sure if there is an easy way to check the count of current running. If there is I'm sure someone will be comment on that. But you can keep references to each task and check its status.
Related
I'm new to Android and Java. I'm trying to download 1000 plus images. I don't want to do that serially in a UI thread as that will be slow. Hence, I implemented multi-threading using thread and runnable in the below manner.
The for-loop will be called 1000 plus times. So is it an efficient way of achieving it? Will the OS manage the thread pool by its own?
private void syncS3Data() {
tStart = System.currentTimeMillis();
try {
for (final AWSSyncFile f : awsSyncData.getFiles()) {
new Thread(new Runnable() {
#Override
public void run() {
beginDownload(f);
}
}).start();
}
} catch (Exception ex) {
progressDialog.dismiss();
showMessage("Error:" + ex.getStackTrace().toString());
}
}
for Sure you can't do that in MainThread (UI Thread) because if you did, the application will not be responding.. and then it will be killed by system, you can use AsyncTask class in order to do what do you need but i prefer to use intentservice
However you have to use Intentservice it's a worker thread (long operation) but be noted intentservice will not execute anything until it finish the current task, if you need to download it in parallel then you have to use Service it works with UI Thread so you need asyncTask in order to perform the action but make sure of calling stopSelf() unlike intentService it will be stopped once it finish
Instead of creating threads for each download, create one thread and use that for downloading all images.
You can use AsyncTask Refer: https://developer.android.com/reference/android/os/AsyncTask.html
private class DownloadFilesTask extends AsyncTask<SomeObject, Integer, Long> {
protected Long doInBackground(SomeObject... objs) {
for (final AWSSyncFile f : obj.getFiles()) {
beginDownload(f);
}
}
protected void onPostExecute(Long result) {
//Task Completed
}
new DownloadFilesTask().execute(someObj);
I had developed an e-commerce app before and have encountered a similar problem in which I had to download some 200+ images for each category.The way I did it was using a loop within an AsyncTask and after each download was completed the image was displayed at the relevant place using the onProgessUpdate() function.I can't share the actual code,so i will give a skeleton example.
public class DownloadImages extends AsyncTask<String,String,String>
{
File image;
protected String doInBackground(String... params)
{
//download the image here and lets say its stored in the variable file
//call publishProgress() to run onProgressUpdate()
}
protected void onProgressUpdate(String... values)
{
//use the image in variable file to update the UI
}
}
I'm trying to execute some code parallel with threads using async task.
But for some reason in android 4.2.2 doesn't work.
I have this code which is in main class:
new XmlDownloader();
task=new SendTask().execute("");
and the following classes:
private class SendTask extends AsyncTask<String,String,String>{
#Override
protected void onPreExecute(){
}
#Override
protected String doInBackground(String...strings){
while(true){
Log.w("outside", "hello");
}
}
return strings[0];
}
#Override
protected void onPostExecute(String country){
}
}
and
public class XmlDownloader extends Activity {
public XmlDownloader(int pos) {
DownloaderTask task = new DownloaderTask();
task.execute("");
}
private String downloadXml(String s,int pos1) {
return null;
}
private class DownloaderTask extends AsyncTask<String, Void, String> {
public DownloaderTask() {
}
#Override
// Actual download method, run in the task thread
protected String doInBackground(String... params) {
while(true){
Log.w("down", "asdasdasssasdasdasdasd");
if(isCancelled())
return null;
};
return null;
}
#Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(String bitmap) {
}
}
}
In android 2.3.3 the logcat shows this sequence
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("outside", "hello");
Log.w("outside", "hello");
Log.w("down", "asdasdasssasdasdasdasd");
but in android 4.2.2 only shows
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Any ideas why threads don't work?
Using AsyncTask may not give you the true parallelism that you need. Across different versions of Android, the number of AsyncTasks that can run simultaneously has been changed from 1 to 5 and then back to 1 (If I'm not wrong).
https://github.com/android/platform_frameworks_base/commits/master/core/java/android/os/AsyncTask.java
https://groups.google.com/forum/?fromgroups#!topic/android-developers/8M0RTFfO7-M
AsyncTasks are backed by a ThreadPool over which you have no control. If AsyncTask doesn't fit your needs, is to use Services or Loopers or build your own ThreadPoolExecutor. AsyncTask is not designed to loop idefinitely, that is to be a server or a service.
So what is happening is that in your Android version only the first enqueued thread from the pool is executed and since it doesn't terminate (they will be run sequentially), the second one never starts.
This has to do with the way AsyncTasks have evolved since their conception in API 3. In API 3, AsyncTasks(plural) were executed serially. This was changed to a pool of threads, allowing multiple AsyncTasks to run in parallel (API 4(DONUT)). But, starting HONEYCOMB(API 11), AsyncTasks are back to being executed serially.
Looking at the output you have provided, both SendTask & DownloaderTask execute in parallel in case of 2.3.3 which is > DONUT and < HONEYCOMB. But, in case of 4.2.2, serial execution of AsyncTasks takes place. Since DownloaderTask is executed first, SendTask waits for it to finish execution(which won't happen thanks to while(true)) --> hence, no output.
Since API 11, you have a choice over whether your AsyncTasks run serially or in parallel. For serial execution, use execute(Params... params). For parallel execution, look into executeOnExecutor(Executor exec, Params... params).
I would like to have an application which either loads or saves data through a HTTP request, however the data must interact with the UI thread. Ideally, I would like a single thread to use an IF statement on a message to determine if the request is to "load" or "save".
What would be the simplest way of doing this with the smallest amount of code?
Also, do instances of Handlers run on individual threads?
EDIT: This is the code I am using now:
Handler doStuff = new Handler(){
#Override
public void handleMessage(Message msg){
if(msg.what == 1){
// Load all the information.
// Get the ID from sharedPrefs
SharedPreferences details= getSharedPreferences("details", 0);
String ID = patDetails.getString("id", "error");
// Load up the ID from HTTP
String patInfo = httpInc.getURLContent("info.php?no="+AES.encrypt("387gk3hjbo8sgslksjho87s", ID));
// Separate all the details
patientInfo = patInfo.split("~");
}
if(msg.what == 2){
// Save the data
}
}
};
Eclipse halts the debugging and displays, "Source not found" for StrictMode.class
I suppose it's because it's using the Main thread to access the internet although it's running in individual threads.
Any idea.
Handlers do run on individual threads. Check that link. You should also check out AsyncTask.
I would propose submitting the jobs as Runnable to a single-threaded ExecutorService:
public class SomeClass {
private ExecutorService execService = Executors.newSingleThreadExecutor();
public void doSomething() {
final String someUiData = // retrieve data from UI
execService.submit(new Runnable() {
#Override
public void run() {
// so something time-consuming, which will be executed asynchronously from the UI thread
// you can also access someUiData here...
}
});
}
}
This way, the UI thread will not block whereas you can easily submit a different Runnable for different operations and the ExecutorService will completely take care of keeping it async.
Edit: If you need to interact with the UI, do so before becoming asynchronous and keep the result in final variables.
I'm creating a reader application. The reader identifies based on the parameters which file to read, does some processing and returns the result to the caller.
I am trying to make this multi-threaded, so that multiple requests can be processed. I thought it was simple but later realized it has some complexity. Even though i create threads using executor service, I still need to return the results back to the caller. So this means waiting for the thread to execute.
Only way i can think of is write to some common location or db and let the caller pick the result from there. Is there any approach possible?
Maybe an ExecutorCompletionService can help you. The submitted tasks are placed on a queue when completed. You can use the methods take or poll depending on if you want to wait or not for a task to be available on the completion queue.
ExecutorCompletionService javadoc
Use an ExecutorService with a thread pool of size > 1, post custom FutureTask derivatives which override the done() method to signal completion of the task to the UI:
public class MyTask extends FutureTask<MyModel> {
private final MyUI ui;
public MyTask(MyUI toUpdateWhenDone, Callable<MyModel> taskToRun) {
super(taskToRun);
ui=toUpdateWhenDone;
}
#Override
protected void done() {
try {
// retrieve computed result
final MyModel computed=get();
// trigger an UI update with the new model
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ui.setModel(computed); // set the new UI model
}
});
}
catch(InterruptedException canceled) {
// task was canceled ... handle this case here
}
catch(TimeoutException timeout) {
// task timed out (if there are any such constraints).
// will not happen if there are no constraints on when the task must complete
}
catch(ExecutionException error) {
// handle exceptions thrown during computation of the MyModel object...
// happens if the callable passed during construction of the task throws an
// exception when it's call() method is invoked.
}
}
}
EDIT: For more complex tasks which need to signal status updates, it may be a good idea to create custom SwingWorker derivatives in this manner and post those on the ExecutorService. (You should for the time being not attempt to run multiple SwingWorkers concurrently as the current SwingWorker implementation effectively does not permit it.)
I have an application the leans heavily on map functionality. From the first Activity I call the runOnFirstFix() method to load a lot of data from a database once the location of the user has been found, but I also want to be able to interrupt this runnable and stop it mid execution for when I switch activity or the user presses the button to stop it running.
myLocationOverlay.runOnFirstFix(new Runnable() {
public void run() {
mc.animateTo(myLocationOverlay.getMyLocation());
mc.setZoom(15);
userLatitude = myLocationOverlay.getMyLocation().getLatitudeE6();
userLongitude = myLocationOverlay.getMyLocation().getLongitudeE6();
userLocationAcquired = true;
loadMapData(); //Here the method is called for heavy data retrieval
}
});
How can I stop this Runnable mid execution?
You could (and probably should) use an AsyncTask
private class MapLoader extends AsyncTask<Void, Void, Data> {
#Override
protected Data doInBackground(Void... params) {
return loadMapData(); //Here the method is called for heavy data retrieval, make it return that Data
}
#Override
protected void onPostExecute(Data result) {
//do things with your mapview using the loaded Data (this is executed by the uithread)
}
}
and then in replace your other code with
final MapLoader mapLoader = new MapLoader();
myLocationOverlay.runOnFirstFix(new Runnable() {
public void run() {
mc.animateTo(myLocationOverlay.getMyLocation());
mc.setZoom(15);
userLatitude = myLocationOverlay.getMyLocation().getLatitudeE6();
userLongitude = myLocationOverlay.getMyLocation().getLongitudeE6();
userLocationAcquired = true;
mapLoader.execute();
}
});
then you should be able to cancel the running task when you no longer want it to complete using
mapLoader.cancel(true);
I hope the code compiles, I haven't tested it, but it should work :)
Just make sure that it is the ui thread that creates the MapLoader
edit: I think you need to wrap the mapLoader.execute(); call in a runOnUiThread() call in order for it to work correctly since runOnFirstFix() might spawn a new thread
use the handler object to handle this runnable.
define this runnable with the runnable object.
after that in handler you can start the cancel this runnable service
for e.g.
Handler handler = new Handler();
on startCommand()
handler.postDelayed(myRunnable,5000);
this will execute the run method of runnable after 5 sec
for cancel
handler.removeCallbacks(myRunnable);
and your runnable define like this way
private Runnable myRunnable = new Runnable(){
public void run(){
// do something here
}
}
http://developer.android.com/reference/android/os/Handler.html
http://developer.android.com/reference/java/util/logging/Handler.html
http://www.vogella.de/articles/AndroidPerformance/article.html
In Java, you can call interrupt() on a running thread which should stop the execution of given thread. But if any kind of blocking operation like wait() or join() is being performed, InterruptedException will be thrown. Even some kinds of socket-related blocking operations can lead to InterruptedIOException under Linux, or under Windows the operation still remains blocked (since Windows does not support interruptible I/O). I think you still could interrupt your runnable, just be aware that some I/O may not be interrupted until finished and if blocking, it might throw those kind of exceptions I mentioned.