Дождаться завершения работы второго потока

72
27 ноября 2021, 10:30

Есть слушатель в главном потоке, он должен ждать ответа из другого потока. Вот пример:

//ГЛАВНЫЙ ПОТОК

add("test", new listener() {
                @Override
                public void run(int index, Object obj) {
                    //ЭТО ВЫПОЛНЯЕТ ВТОРОЙ ПОТОК, через определенное время
                    //ЗАВЕРШИТЬ ОЖИДАНИЕ ГЛАВНОГО ПОТОКА, ТОЕСТЬ RUN ВЫПОЛНЕН
                }
            });

//ГЛАВНЫЙ ПОТОК должен ожидать завершения выполнения run!

Answer 1

Метод класса Thread:

public final void join();

Этот метод ожидает завершения того потока исполнения, для которого он был вызван­. Его имя отражает следующий принцип: вызывающий поток ожидает, когда указанный поток присоединится к нему. Дополнительные формы метода jоin() позволяют вызывать максимальный промежуток времени, в течение которого требуется ожидать завершения указанного потока исполнения.

Значит Вам в главном потоке, необходима получить ссылку потока_2 и заставить главный поток остановиться ожидая поток_2, методом:

ссылкаНаПоток_2.join();

в этот момент главный поток остановится и будет ожидать завершение потока: ссылкаНаПоток_2, как только поток_2 отработает возобновит работу главный поток.

А вообще посмотрите лекции по роботе с потоками (там 4 лекции вроде) https://www.youtube.com/watch?v=0FvbIGNUl8A - Иван Головач, очень не плохо тему доводит

Answer 2

Как же все-таки правильно заставить поток уснуть и разбудить его из второго потока, сами исходники с официального oracle(но в одной функции)

public boolean setSleep(boolean newSleep){
        if(newSleep!=sleep){
            if(newSleep == true){ //ЗНАЧ ДОЛЖЕН СПАТЬ, вызывать в первом потоке!
                synchronized (obj) {
                    sleep = true;
                    while (sleep) {
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            if(newSleep == false){ //ВЫЗЫВАТЬ ИЗ ВНЕ
                synchronized (obj) {
                    sleep = false;
                    obj.notifyAll();
                }
            }
            return true;
        }
        return false;
    } ,SLEEP - BOOLEAN (по умолчанию false), obj (простой обьект нужен для синхронизации, Object obj = new Object()(можно и без него, указать synchronized в функции, но не тестил))
Answer 3

Я долго искал решения , мне нужно было подождать пока Appsflyer инициализируется. Я пытался использовать Thread но єто останавливало UI. В итоге я использовал AsyncTask

    AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(8000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                loadLink();
            }
        });
Answer 4

Как вариант, если нужно чтобы main thread ждал окончания нескольких потоков, можно использовать ещё такой вариант

while (true){
        if(!onethread.isAlive() && !twothread.isAlive() && !threethread.isAlive()) {
            do something in main thread
            break;
        }
    }
READ ALSO
Как передать список MultipartFile в контроллер?

Как передать список MultipartFile в контроллер?

У меня есть такой контроллер (поменять его не могу):

202
Не отображаются предметы в RecycleView

Не отображаются предметы в RecycleView

я новичок в Android StudioЯ делаю приложение заметочник, используя RecycleView и для сохранения заметок SQLite

102