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

时间:2016-03-30 12:19:45

标签: java multithreading firebase-authentication

说我正在使用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。

3 个答案:

答案 0 :(得分:3)

您应该使用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),它不会捕获中断的异常并永久阻塞。我也不建议这样做。忙碌的等待几乎不是一个好主意。

答案 1 :(得分:2)

non-Android runtimes上,Firebase Java客户端使用daemon threads,这不会阻止进程退出。您必须使用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();
    }

}

<强> Semaphore

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

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();
    }

}

答案 2 :(得分:0)

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

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