Ждите обратного вызова из другого потока - PullRequest
2 голосов
/ 12 февраля 2020

Прежде всего, я решил сделать блокировку своего класса (чтобы потребителю было проще пользоваться - но, возможно, мне было бы труднее писать). В противоположность тому, чтобы потребитель определял асинхронные обратные вызовы. Это хороший шаблон дизайна? Таким образом, пользователь может получить ожидаемое поведение, но реализовать собственную многопоточность, если он недоволен тем, как долго блокируется поток.

У меня есть конструктор, который устанавливает конечное поле в классе на основе результата асинхронного обратного вызова c:

class Example {
    private final int x;

    Example(){
        asyncFunc(/* callback */ result -> x = result)
    }
}

Это не работает, поэтому я использовал ссылки на atomi c и реализовал блокировку l oop, пока возвращенный результат, вот так:

class Example {
    private final int x;

    Example(){
        x = waitAsyncFunc();
    }

    private int waitAsyncFunc(){
        AtomicBoolean finished = new AtomicBoolean(false);
        AtomicReference<byte[]> result = new AtomicReference<>();
        asyncFunc(result -> {
            result .set(res);
            finished.set(true);
        });
        while (!finished.get()) { /* No op */ }
        return result.get();
    }

}

Это хороший способ заблокировать / получить результат?

Ответы [ 2 ]

3 голосов
/ 12 февраля 2020

Самое простое решение было бы

class Example {
    private final int x;

    Example() {
        CompletableFuture<Integer> f = new CompletableFuture();
        asyncFunc(f::complete);
        x = f.join();
    }
}

Но рассмотрим альтернативу ожидания завершения асинхронного задания, прежде чем даже создать экземпляр Example.

3 голосов
/ 12 февраля 2020

Вместо блокировки потока с помощью oop вы можете использовать CountDownLatch .

Как взято из документов (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)

Средство синхронизации, позволяющее одному или нескольким потокам дождаться завершения набора операций, выполняемых в других потоках.

Ваш код будет выглядеть примерно так:

private int waitAsyncFunc() throws InterruptedException {
        CountDownLatch latch = new new CountDownLatch(1);
        AtomicReference<byte[]> result = new AtomicReference<>();
        asyncFunc(result -> {
            result.set(res);
            latch.countDown();
        });
        latch.await(); //You can even specify a timeout
        return result.get();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...