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

时间:2014-11-28 00:18:16

标签: java gwt

我在列表上有一个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循环中的所有异步操作何时完成?

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分: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。一旦它成立,就使用一些回调。

答案 2 :(得分: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);
        }
    }
}