【问题标题】:Wait for callback from other thread等待来自其他线程的回调
【发布时间】:2023-03-21 22:14:01
【问题描述】:

首先,我决定让我的类阻塞(让消费者更容易使用 - 但可能对我来说更乏味)。与让消费者定义异步回调相反。这是一个好的设计模式吗?这样,用户可以获得预期的行为,但如果他们对线程阻塞的时间不满意,可以实现自己的多线程。

我有一个构造函数,它根据异步回调的结果在类中设置最终字段:

class Example {
    private final int x;

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

这不起作用,所以我使用了原子引用,并实现了一个阻塞循环,直到它返回结果,如下所示:

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

}

这是阻止/检索结果的好方法吗?

【问题讨论】:

  • 您可以使用 CountDownLatch (stackoverflow.com/questions/17827022/…),而不是使用 AtomicBoolean 等待线程完成。基本上,您定义了一个锁存器,它必须多久倒计时一次。使用 await 您可以暂停线程,直到闩锁倒计时到 0。
  • 为什么必须在示例类中等待结果?
  • 只是一个例子@You'reawesome。在我的实际课程中,(阻塞和异步)方法都在我的课程中
  • 一般来说,我认为在 lambda 中重新分配变量不是一个好主意。我会创建另一个异步函数来处理asyncFunc 返回的结果
  • @You'reawesome 我不明白你的意思

标签: java multithreading concurrency


【解决方案1】:

您可以使用 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();
    }

【讨论】:

    【解决方案2】:

    最简单的解决方案是

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

    但考虑在构建Example 实例之前等待异步作业完成的替代方案。

    【讨论】:

    • 完美。根据您的建议,您的意思是将异步结果作为参数传递给构造函数吗?这对于类的每个实例化都会重复 - 使类的使用变得复杂
    • 这可以通过工厂方法避免。只是一个建议。我倾向于避免在构造函数中阻塞操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多