Reputation: 443
I'm building an Android
app and I have some issues with the architecture - how to implement many calls on different threads.
I have 2 methods:
ConnectAndGetId() //takes 2-3 seconds
GetTokenID(ID) //takes 2-3 seconds
First I need to call ConnectAndGetId()
and then after getting a result ID
to call GetTokenID(ID)
.
After I get a tokenID
I need to call 4 methods and pass them tokenID
:
getNames (tokenID) //takes 4 second
getPhones (tokenID) //takes 7 seconds
getIds(tokenID) //takes 2 seconds
getDetailObject(tokenID) //takes 5 seconds
The idea is to show the data ONLY after I have the result from the ALL 4 methods. There is no need to execute them one by one because It will take a lot of time (18 sec), I want to run them in parallel and in the end with all the data to update the UI
.
I thought to do the next thing:
Start AsyncTask
and call to ConnectAndGetId
,in onPostExecute()
start another AsyncTask
and run there GetTokenID(ID)
. after I run GetTokenID(ID)
I'll return the
result to UI
thread and with the returned data I'll start 4 new threads
, that each thread will call one of the 4 methods. I can count the finished threads,and when I got all the 4 result I can update the UI
with handler.
Is it the right approach ? maybe I should not create 4 threads for 4 methods? else to create one handlerThread
and pass the 4 methods to his handler so the Thread will pool them - but it will be one by one.
Is that the correct idea or It can be done better?
Upvotes: 0
Views: 358
Reputation: 8415
Regarding if running four threads is appropriate for your situation only you can judge. It increases the complexity of the program and requires multithread access protection and synchronization on relevant data. Also consider if parallel access can actually speed up your computation. Parallel access only speeds up if the limiting factor is single-thread computational speed, if the limit lies with data bandwidth you won't see any significant gain in speed.
To your problem of four threads complete to one UI update you can try using a CyclicBarrier to lock all threads until the last one finishes execution.
The following shows an example:
// Create a CyclicBarrier with 4 parties and a target action to update UI
CyclicBarrier barrier = new CyclicBarrier(4, new Runnable(){
public void run(){
//Do your UI updates here (remember any direct UI must be on UI thread)
}
});
// Pass above CyclicBarrier to your four threads
// Skeleton of Runnable instance for each of the four threads.
Runnable r = new Runnable(){
public void run(){
// Run desired long-running method
// getNames, getPhones, etc
// Call await() from CyclicBarrier instance (exception handling not shown)
barrier.await();
}
};
With the above code each thread that finishes will block on the await method until the fourth thread calls await()
in which all threads unblock and the last thread runs the runnable passed to the CyclicBarrier at the start.
Upvotes: 0
Reputation: 6855
It's normal approach. But I would recommend you to use Executor
but not create Threads
. Sample:
public class TasksSample {
public static void execute(){
ExecutorService executorService = Executors.newFixedThreadPool(4);
executorService.submit(new Task("A"));
executorService.submit(new Task("B"));
executorService.submit(new Task("C"));
executorService.submit(new Task("D"));
executorService.shutdown();
try {
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("all tasks finished");
}
private static class Task implements Runnable{
private String taskId;
public Task(String taskId) {
this.taskId = taskId;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finished task: " + taskId);
}
}
}
Upvotes: 1
Reputation: 599
Very good question indeed. I think your aproach is correct, but I wouldn't create the GetTokenID thread on the onPostExecute(). I think it's better to use a Listener to ensure that you got the result you need. On the next step I would also use a Listener that would call your 4 methods.
The question is: do you need the 4 methods to finish to update your UI? then you should use a Listener with a synchronized block that would only enter when your 4 methods have finished. You can use a method that checks that these methods have got their results and when the 4 have completed, update the UI.
In case you don't need the 4 methods to finish to update the UI I would just put a ProgressDialog in the UI and update it method-by-method. In the last one dismiss the ProgressDialog and unblock the UI.
I hope it helps you out bro, good luck with coding!
Upvotes: 0