结束语异步计算成一个同步(阻塞)计算 [英] Wrapping an asynchronous computation into a synchronous (blocking) computation

查看:225
本文介绍了结束语异步计算成一个同步(阻塞)计算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

类似的问题:

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

在这里ImplementingThing需要投入,做一些神秘的东西,就像在一个任务队列进行排队的东西,再后来当结果出现时, sink.onBazResult()被调用上螺纹可能会或可能不会在同一线程ImplementingThing.doSomethingAsync()被调用。

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.

有没有一种方法我可以使用事件驱动的功能我有,并发原语一起,实现MyNiceInterface所以脚本客户可以愉快地等待一个阻塞线程?

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?

编辑:我使用的此FutureTask提供

推荐答案

使用自己的未来实行:

public class BazComputationFuture implements Future<Baz>, BazComputationSink {

    private volatile Baz result = null;
    private volatile boolean cancelled = false;
    private final CountDownLatch countDownLatch;

    public BazComputationFuture() {
        countDownLatch = new CountDownLatch(1);
    }

    @Override
    public boolean cancel(final boolean mayInterruptIfRunning) {
        if (isDone()) {
            return false;
        } else {
            countDownLatch.countDown();
            cancelled = true;
            return !isDone();
        }
    }

    @Override
    public Baz get() throws InterruptedException, ExecutionException {
        countDownLatch.await();
        return result;
    }

    @Override
    public Baz get(final long timeout, final TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException {
        countDownLatch.await(timeout, unit);
        return result;
    }

    @Override
    public boolean isCancelled() {
        return cancelled;
    }

    @Override
    public boolean isDone() {
        return countDownLatch.getCount() == 0;
    }

    public void onBazResult(final Baz result) {
        this.result = result;
        countDownLatch.countDown();
    }

}

public Future<Baz> doSomething(Foo fooArg, Bar barArg) {
    BazComputationFuture future = new BazComputationFuture();
    doSomethingAsync(fooArg, barArg, future);
    return future;
}

public Baz doSomethingAndBlock(Foo fooArg, Bar barArg) {
    return doSomething(fooArg, barArg).get();
}

的解决方案创建内部的CountDownLatch一旦接收回调被清除。如果用户来电得到的,CountDownLatch被使用,直到计算完成对阻塞调用线程,并调用onBazResult回调。该CountDownLatch将保证如果GET之前发生回调()被调用的get()方法将结果立即返回。

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.

这篇关于结束语异步计算成一个同步(阻塞)计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆