我正在构建一个Android
应用程序,我在架构上遇到了一些问题 - 如何在不同的线程上实现多个调用。
我有两种方法:
ConnectAndGetId() //takes 2-3 seconds
GetTokenID(ID) //takes 2-3 seconds
首先,我需要致电ConnectAndGetId()
,然后在获得结果ID
后致电GetTokenID(ID)
。
获得tokenID
后,我需要调用4种方法并将其传递给tokenID
:
getNames (tokenID) //takes 4 second
getPhones (tokenID) //takes 7 seconds
getIds(tokenID) //takes 2 seconds
getDetailObject(tokenID) //takes 5 seconds
我的想法是在获得 ALL 4方法的结果后显示数据 ONLY 。没有必要逐个执行它们,因为它需要花费很多时间(18秒),我想并行运行它们,最后用所有数据来更新UI
。
我想做下一件事:
开始AsyncTask
并致电ConnectAndGetId
,在onPostExecute()
开始另一个AsyncTask
并在那里GetTokenID(ID)
运行。在我运行GetTokenID(ID)
后,我将返回
结果到UI
线程,并且返回的数据我将开始4个新的threads
,每个线程将调用4个方法中的一个。我可以计算完成的线程,当我得到所有4个结果时,我可以用处理程序更新UI
。
这是正确的方法吗?也许我不应该为4种方法创建4个线程?否则创建一个handlerThread
并将4个方法传递给他的处理程序,这样Thread就可以将它们集中在一起 - 但它将是一个接一个的。
这是正确的想法还是可以做得更好?
答案 0 :(得分:1)
这是正常的做法。但我建议您使用Executor
但不要创建Threads
。样品:
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);
}
}
}
答案 1 :(得分:0)
问题是:您是否需要4种方法来完成更新UI?那么你应该使用一个只有你的4个方法完成时才会进入的同步块的监听器。您可以使用检查这些方法是否已获得结果的方法以及4完成后更新UI。
如果您不需要4个方法来完成更新UI,我只需在UI中放入ProgressDialog并逐个方法地更新它。在最后一个中,关闭ProgressDialog并取消阻止UI。
我希望它能帮助你解决问题,祝你好运!
答案 2 :(得分:0)
关于如果运行四个线程适合您的情况,您只能判断。它增加了程序的复杂性,并且需要对相关数据进行多线程访问保护和同步。还要考虑并行访问是否可以真正加快计算速度。如果限制因素是单线程计算速度,并行访问只会加速,如果限制在于数据带宽,则不会看到任何显着的速度增益。
对于完成一个UI更新的四个线程的问题,您可以尝试使用CyclicBarrier锁定所有线程,直到最后一个完成执行。
以下是一个示例:
// 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();
}
};
使用上面的代码,每个完成的线程将阻塞await方法,直到第四个线程调用await()
,其中所有线程都解除阻塞,最后一个线程运行runnable,在开始时传递给CyclicBarrier。