有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

我通过谷歌搜索找到的所有其他解决方案只有在我能够访问库中使用的线程变量的情况下才有效。但我无法接触到这些

以下是我目前正在使用的内容:

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客户端jvm测试firebase


共 (3) 个答案

  1. # 1 楼答案

    一个CountdownLatch对于让一个线程等待一个或多个线程在继续之前完成一个或多个任务来说是非常好的

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

  2. # 2 楼答案

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

  3. # 3 楼答案

    non-Android runtimes上,Firebase Java客户端使用daemon threads,这不会阻止进程退出。必须使用CountdownLatchSemaphore来处理此问题

    CountdownLatch

    A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

    上面的代码:

    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()调用中)。在您的代码中,创建时没有可用的“票证”:

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