如何知道For循环中的所有异步操作何时完成?

3

我有一个针对列表的for循环:

boolean initialized = false
for(final Share share : shares) {

    someInstance.check(new someCallback() {
        @Override
        public void onSuccess() {
            // do something
        }
    });         
}
initialized = true;

在每一步中,都会执行一个名为check()的异步操作。当所有check()操作完成时,我想将initialized设置为true。是否有一种方法可以在Java/GWT中实现这个目标?

如何知道for循环中的所有异步操作何时完成?


someCallback 是一个接口还是一个类?如果是一个类,你可以添加一个静态的布尔方法 processedAll() 或者其他什么,以及一个静态的 someCallback[]。该方法循环遍历数组,检查每个回调是否已经完成。实际上有几种方法可以做到这一点。知道 someCallback 是一个类还是接口会很好。 - Dioxin
3个回答

3
每次调用onSuccess时,只需增加一个共享计数器,该计数器记录已完成的数量。你知道你已经开始了多少个(比如说N),所以一旦完成计数器达到相同的值(N),就知道它们全部都已经完成了。然后最后一个完成的将设置initialized = true

或者倒数到0,这样除了初始化计数器的地方,没有任何东西需要知道一个神奇的数字。 - zapl
@zapl 是的,那样会更好。 - peter.petrov

2

我不知道GWT是否有任何特殊限制,但是你可以等待它们全部成功完成,例如使用一个简单的CountDownLatch

    final CountDownLatch latch = new CountDownLatch(shares.size());
    for(final Share share : shares) {
        someInstance.check(new someCallback() {
            @Override
            public void onSuccess() {
                latch.countDown();
                // do something
            }
        });         
    }
    latch.await();
    boolean initalized = true;

这将简单地阻塞执行,直到每个回调函数都减少了一次计数。然而,阻塞通常是一个不好的主意。因此,您可能还希望异步设置initialized,并在它为真时使用一些回调函数。


0
你可以使用这个回调计数器实现。当所有回调完成时,它会触发提供的AsyncCallback。类似于Promise.all()。该实现具有锁定和解锁方法,以确保某些回调不会在必要时进行计数。
以下是如何使用它:
CallbackCounter counter = new CallbackCounter(yourFinalCallback);
//counter.lock(); call this if methodWithCallback may execute callback synchronously
for (int i = 0; i < 10; i++)
{
    AsyncCallback<Void> counterCallback = counter.async();
    methodWithCallback(i, counterCallback);
}
//counter.unlock();

这是CallbackCounter类:

public class CallbackCounter
{

    private int count;
    private int maxCount;
    private boolean failOnError;
    private Throwable exceptionDuringLock;

    private boolean unlocked;
    private AsyncCallback<Void> callback;

    public CallbackCounter(AsyncCallback<Void> callback)
    {
        this(true, callback);
    }

    public CallbackCounter(boolean failOnError, AsyncCallback<Void> callback)
    {
        this.failOnError = failOnError;
        this.callback = callback;

        count = 0;
        maxCount = 0;
        unlocked = true;
    }

    public int getCount()
    {
        return maxCount;
    }

    public LocalDatabaseRemoveCallback localDatabaseRemove()
    {
        maxCount++;

        return new LocalDatabaseRemoveCallback()
        {
            @Override
            public void onRemove(String key)
            {
                counterSuccess();
            }

            @Override
            public void onError(String key, Throwable error)
            {
                counterFail(error);
            }
        };
    }

    public AsyncCallback<Void> async()
    {
        maxCount++;

        return new AsyncCallback<Void>()
        {
            @Override
            public void onSuccess(Void result)
            {
                counterSuccess();
            }

            @Override
            public void onFailure(Throwable caught)
            {
                counterFail(caught);
            }
        };
    }

    public CommandCallback<Void> command()
    {
        maxCount++;

        return new CommandCallback<Void>()
        {
            @Override
            public void onCallback(Void data)
            {
                counterSuccess();
            }
        };
    }

    public SimpleCallback simple()
    {
        maxCount++;

        return new SimpleCallback()
        {
            @Override
            public void onCallback()
            {
                counterSuccess();
            }
        };
    }

    public void lock()
    {
        if (unlocked)
        {
            unlocked = false;
        }
    }

    public void unlock()
    {
        if (!unlocked)
        {
            unlocked = true;

            if (count >= maxCount)
            {
                if (exceptionDuringLock == null)
                {
                    conterSuccessCallback();
                }
                else
                {
                    Throwable e = exceptionDuringLock;
                    exceptionDuringLock = null;

                    conterFailCallback(e);
                }
            }
        }
    }

    private void counterSuccess()
    {
        count++;

        if (!unlocked)
        {
            return;
        }

        if (count >= maxCount)
        {
            conterSuccessCallback();
        }
    }

    private void conterSuccessCallback()
    {
        if (callback != null)
        {
            AsyncCallback<Void> callbackToCall = callback;
            callback = null;

            callbackToCall.onSuccess(null);
        }
    }

    private void counterFail(Throwable caught)
    {
        count++;

        if (failOnError)
        {
            if (unlocked)
            {
                conterFailCallback(caught);
            }
            else
            {
                exceptionDuringLock = caught;
            }
        }
    }

    private void conterFailCallback(Throwable caught)
    {
        if (callback != null)
        {
            AsyncCallback<Void> callbackToCall = callback;
            callback = null;

            callbackToCall.onFailure(caught);
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接