如何等待所有线程完成执行?

假设我正在使用HTTP请求库来下载文件。 这个库使用里面的线程。 现在,我想等待主线程,直到其他线程完成执行。

通过google搜索找到的所有其他解决方案只有在我有权访问库中使用的Thread变量时才有效。 但这些都不适合我。

这是我目前使用的:

package smartzero.eightnoteight.testfirebase; import com.firebase.client.AuthData; import com.firebase.client.Firebase; import com.firebase.client.FirebaseError; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("email: "); String email = in.nextLine(); System.out.print("password: "); String password = in.nextLine(); Firebase fb = new Firebase("https://nullform.firebaseio.com"); fb.authWithPassword(email, password, new AuthResultHandler()); try { Thread.sleep(1000000); } catch (InterruptedException e) { e.printStackTrace(); } } public static class AuthResultHandler implements Firebase.AuthResultHandler { @Override public void onAuthenticated(AuthData authData) { System.out.println("authentication successful"); String uid = authData.getUid(); new RunTests(uid); } @Override public void onAuthenticationError(FirebaseError firebaseError) { System.out.println("authentication failed."); } } } 

PS:我在我的电脑上使用firebase-client-jvm测试firebase。

您应该使用Firebase提供的活动:

 fb.authWithPassword(email, password, new AuthResultHandler(){ @Override public void onAuthenticated(AuthData authData) { //do something if authentication successful } @Override public void onAuthenticationError(FirebaseError error) { //handle error } }); 

你可以,如果你真的想在主要等待这样做:

 void main(String[] args) { boolean finished = false; fb.authWithPassword(email, password, new AuthResultHandler(){ @Override public void onAuthenticated(AuthData authData) { finished = true; } }); while (!finished){ Thread.sleep(1); } } 

这更像是一种伪代码。 如果出现错误(onAuthenticationError),它不会捕获中断的exception并永远阻塞。 我也不建议这样做。 忙碌的等待几乎不是一个好主意。

在非Android运行时 ,Firebase Java客户端使用守护程序线程 ,这不会阻止进程退出。 您必须使用CountdownLatchSemaphore处理此问题。

CountdownLatch

允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。

你的代码:

 package smartzero.eightnoteight.testfirebase; import com.firebase.client.AuthData; import com.firebase.client.Firebase; import com.firebase.client.FirebaseError; import java.util.Scanner; import java.util.concurrent.CountDownLatch; public class Main { public static void main(String[] args) throws InterruptedException { Scanner in = new Scanner(System.in); System.out.print("email: "); String email = in.nextLine(); System.out.print("password: "); String password = in.nextLine(); in.close(); Firebase fb = new Firebase("https://nullform.firebaseio.com"); CountDownLatch done = new CountDownLatch(1); fb.authWithPassword(email, password, new Firebase.AuthResultHandler(){ @Override public void onAuthenticated(AuthData authData) { System.out.println("authentication successful"); done.countDown(); } @Override public void onAuthenticationError(FirebaseError error) { System.out.println("authentication failed."); done.countDown(); } }); done.await(); } } 

信号

它用于控制使用资源的并发线程数。 您可以将其视为使用资源的票证。 您可以在创建时设置可用的票数,并且在没有票证的情况下调用acquire()时,您的进程将等待一个可用(在release()调用上)。 在您的代码上创建时,零“门票”可用:

 package smartzero.eightnoteight.testfirebase; import com.firebase.client.AuthData; import com.firebase.client.Firebase; import com.firebase.client.FirebaseError; import java.util.Scanner; import java.util.concurrent.Semaphore; public class Main { public static void main(String[] args) throws InterruptedException { Scanner in = new Scanner(System.in); System.out.print("email: "); String email = in.nextLine(); System.out.print("password: "); String password = in.nextLine(); in.close(); Firebase fb = new Firebase("https://nullform.firebaseio.com"); Semaphore semaphore = new Semaphore(0); fb.authWithPassword(email, password, new Firebase.AuthResultHandler(){ @Override public void onAuthenticated(AuthData authData) { System.out.println("authentication successful"); semaphore.release(); } @Override public void onAuthenticationError(FirebaseError error) { System.out.println("authentication failed."); semaphore.release(); } }); semaphore.acquire(); } } 

CountdownLatch非常适合让一个线程在继续之前等待一个或多个线程完成一个或多个任务。

首先,创建倒计数锁存器,其计数为n,其中n是您要等待的事件数。 接下来,给一个或多个线程执行工作。 之后,应该等待的线程在锁存器上调用await(),同时其他线程开始工作。 当每个工作线程完成后,它们会调用锁存器上的countdown()。 当锁存计数器达到零时,等待线程(或可能是线程)将解除阻塞。