Как заставить поток ждать отработки слушателя внутри другого класса через wait/notify?

Всем привет. Задача такая: запускаю поток, который в свою очередь подключается к серверу, вытаскивает нужную информацию, компилирует в файл и файл отправляет на другой сервер, затем поток ждет около часа и повторяет операцию. При запуске потока создаю цикл

public void run() {
    while (!isInterrupted()){
        adapter = new ConnectAdapter(this);
        synchronized (adapter) {
            adapter.connect();
            try {
                adapter.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }

}

Затем внутри класса ConnectAdapter происходит вся логика которая собирает инфу и отправляет файл на сервер и в конце вызывает метод notyf. Но основной поток не продолжает свою работу, то есть что бы я не написал после строчки adapter.wait() не выполнится. А задумка в том, что после этого поток запишет время выполнения и уйдет спать на час, а затем все заново. Не могу сообразить как сделать правильное ожидание.


Ответы (1 шт):

Автор решения: Kostya

У вас adapter.connect(); без блокировки? Если с блокировкой, то notify() в нем вызывается раньше чем вы вызываете wait(). Как следствие монитор не сбрасывается и ждет.

Можно использовать шудлер для решения:

ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(new MyThread(), 0, 1, TimeUnit.HOURS);

Поток будет создаваться и выполняться каждый час. Собственно метод должен теперь выглядеть так:

public void run() {
    adapter = new ConnectAdapter(this);
    adapter.connect();
}

Если вы хотите оставить свой вариант то можно использовать Semaphore. Даже если adapter.connect(); с блокировкой, то ваш код будет выполнять так, как вы этого ожидаете.

class MyThread extends Thread {
    private final Semaphore semaphore;

    MyThread() {
        this.semaphore = new Semaphore(1);
    }

    @Override
    public void run() {
        var adapter = new ConnectAdapter(semaphore);

        try {
            adapter.connect();
            semaphore.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

В ConnectAdapter

public void connect() {
    ...
    ...
    ...
    semaphore.release();
}
→ Ссылка