将异步计算包装为同步(阻塞)计算
类似的问题:
我有一个对象,它的方法我想向库客户端(尤其是脚本客户端)公开,如下所示:
interface MyNiceInterface
{
public Baz doSomethingAndBlock(Foo fooArg, Bar barArg);
public Future<Baz> doSomething(Foo fooArg, Bar barArg);
// doSomethingAndBlock is the straightforward way;
// doSomething has more control but deals with
// a Future and that might be too much hassle for
// scripting clients
}
但我可用的原始“东西”是一组事件驱动类:
interface BazComputationSink
{
public void onBazResult(Baz result);
}
class ImplementingThing
{
public void doSomethingAsync(Foo fooArg, Bar barArg, BazComputationSink sink);
}
其中 ImplementingThing 接受输入,执行一些操作诸如将事物排队到任务队列中之类的神秘事物,然后当结果发生时,在与 ImplementingThing.doSomethingAsync() 可能是也可能不是同一线程的线程上调用 sink.onBazResult()
被称为。
有没有一种方法可以使用我拥有的事件驱动函数以及并发原语来实现 MyNiceInterface,以便脚本客户端可以愉快地等待阻塞线程?
编辑:我可以使用FutureTask 为此?
similar questions:
- Pattern for wrapping an Asynchronous JavaScript function to make it synchronous
- Wrapping an asynchronous method synchronously in C#
I have an object with a method I would like to expose to library clients (especially scripting clients) as something like:
interface MyNiceInterface
{
public Baz doSomethingAndBlock(Foo fooArg, Bar barArg);
public Future<Baz> doSomething(Foo fooArg, Bar barArg);
// doSomethingAndBlock is the straightforward way;
// doSomething has more control but deals with
// a Future and that might be too much hassle for
// scripting clients
}
but the primitive "stuff" I have available is a set of event-driven classes:
interface BazComputationSink
{
public void onBazResult(Baz result);
}
class ImplementingThing
{
public void doSomethingAsync(Foo fooArg, Bar barArg, BazComputationSink sink);
}
where ImplementingThing takes inputs, does some arcane stuff like enqueueing things on a task queue, and then later when a result occurs, sink.onBazResult()
gets called on a thread that may or may not be the same thread as ImplementingThing.doSomethingAsync() was called.
Is there a way I can use the event-driven functions I have, along with concurrency primitives, to implement MyNiceInterface so scripting clients can happily wait on a blocking thread?
edit: can I use FutureTask for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
使用您自己的 Future 实现:
该解决方案在内部创建一个 CountDownLatch,一旦收到回调,该 CountDownLatch 就会被清除。如果用户调用 get,则使用 CountDownLatch 来阻塞调用线程,直到计算完成并调用 onBazResult 回调。 CountDownLatch 将确保如果在调用 get() 之前发生回调,则 get() 方法将立即返回结果。
Using your own Future implemenation:
The solution creates a CountDownLatch internally which is cleared once the callback is received. If the user calls get, the CountDownLatch is used to block the calling thread until the computation completes and call the onBazResult callback. The CountDownLatch will assure that if the callback occurs before get() is called the get() method will return immediately with a result.
好吧,有一个简单的解决方案,可以执行以下操作:
当然,这假设您的
Baz
结果永远不会为空......Well, there is the simple solution of doing something like:
Of course, this assumes that your
Baz
result will never be null…google guava 库 有一个易于使用的 SettableFuture,使这个问题变得非常简单(大约10 行代码)。
The google guava library has an easy to use SettableFuture that makes this problem very simple (around 10 lines of code).
使用 RxJava 2.x 这非常简单:
或者没有 Lambda 表示法:
甚至更简单:
Kotlin 版本:
This is dead simple with RxJava 2.x:
Or without Lambda notation:
Even simpler:
Kotlin Version:
java.util.concurrent.CountDownLatch 是一种并发构造,允许一个或多个线程等待一组给定操作完成。
CountDownLatch
使用给定的计数进行初始化。通过调用countDown()
方法来减少此计数。等待此计数达到零的线程可以调用await()
方法之一。调用await()
会阻塞线程,直到计数达到零。下面是一个简单的例子。 Decrementer 在
CountDownLatch
上调用countDown()
3 次后,等待的 Waiter 从await()
调用中释放。您还可以指定一些
TimeOut
来等待。//--------------
参考
如果您不想使用
CountDownLatch
或者您的要求与 Facebook 相似或不同的功能相同。意味着如果正在调用一种方法,则不要调用另一种方法。在这种情况下,您可以声明 a
,然后您可以检查方法调用的开头,如果它是
false
则调用方法,否则返回..取决于您的实现。A
java.util.concurrent.CountDownLatch
is a concurrency construct that allows one or more threads to wait for a given set of operations to complete.A
CountDownLatch
is initialized with a given count. This count is decremented by calls to thecountDown()
method. Threads waiting for this count to reach zero can call one of theawait()
methods. Callingawait()
blocks the thread until the count reaches zero.Below is a simple example. After the Decrementer has called
countDown()
3 times on theCountDownLatch
, the waiting Waiter is released from theawait()
call.You can also mention some
TimeOut
to await.//--------------
Reference
If you don't want to use a
CountDownLatch
or your requirement is something same as Facebook like and unlike functionality. Means if one method is being called then don't call the other method.In that case you can declare a
and then you can check in the beginning of your method call that if it is
false
then call method otherwise return.. depends upon your implementation.这是基于 Paul Wagland 的答案的更通用的解决方案:
这是一个如何使用它的示例::
可以在此处找到更详细的代码版本: http://pastebin.com/hKHJUBqE
编辑:
与该问题相关的示例是:
Here's a more generic solution based on Paul Wagland's answer:
Here's an example how to use it::
A more verbose version of the code can be found here: http://pastebin.com/hKHJUBqE
EDIT:
The example related to the question would be:
最简单的方法(对我有用)是
轮询队列(这就是
你阻止)的结果。
The simplest way (which works for me) is to
Poll the queue (that's where
you block) for the result.