2

CountDownLatch我刚刚开始在我的 Android 应用程序中玩耍。目前我正在尝试向Volley我的 api 发出两个请求,并等到数据被检索和存储后再继续执行线程。

这是我的代码示例:

    // new CountDownLatch for 2 requests
    final CountDownLatch allDoneSignal = new CountDownLatch(2);

    transactions.getResourcesForRealm(Contact.class, "", new ICallBack<Contact>() {
        @Override
        public void onSuccess(ArrayList<Contact> resources, String resourceId) {
            transactions.createRealmObject(resources, Contact.class);

            allDoneSignal.countDown();
        }

        @Override
        public void onFail(ArrayList<Contact> resources) {

        }
    });

    transactions.getResourcesForRealm(Meeting.class, "", new ICallBack<Meeting>() {
        @Override
        public void onSuccess(ArrayList<Meeting> resources, String resourceId) {
            transactions.createRealmObject(resources, Meeting.class);

            allDoneSignal.countDown();
        }

        @Override
        public void onFail(ArrayList<Meeting> resources) {

        }
    });

    try {
        allDoneSignal.await();
        // continue executing code
        // ...
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

问题是它似乎没有“完成”倒计时,因此因为从未释放闩锁而冻结。我已经确认 API 请求正在工作并且onSuccess回调成功命中,但线程挂起。

更新 我刚刚注意到CountDownLatch设置为 0 时,它会命中onSuccess,但是当我将它设置为大于 0 的任何值时,它会冻结并且onSuccess永远不会被调用。线程似乎有些时髦。

4

2 回答 2

6

您的代码太容易出错,您需要调用countDown()finally 块并同时调用它,onFail否则如果失败,您的应用程序将永远冻结。所以你的代码应该是这样的:

transactions.getResourcesForRealm(Contact.class, "", new ICallBack<Contact>() {
    @Override
    public void onSuccess(ArrayList<Contact> resources, String resourceId) {
        try {
            transactions.createRealmObject(resources, Contact.class);
        } finally {
            allDoneSignal.countDown();
        }
    }

    @Override
    public void onFail(ArrayList<Contact> resources) {
        allDoneSignal.countDown();
    }
});

transactions.getResourcesForRealm(Meeting.class, "", new ICallBack<Meeting>() {
    @Override
    public void onSuccess(ArrayList<Meeting> resources, String resourceId) {
        try {
            transactions.createRealmObject(resources, Meeting.class);
        } finally {
            allDoneSignal.countDown();
        }
    }

    @Override
    public void onFail(ArrayList<Meeting> resources) {
        allDoneSignal.countDown();
    }
});
于 2016-08-01T09:07:37.037 回答
2

很抱歉回答迟了,但如果它仍然对任何人有帮助:

您需要在单独的线程中执行“.await”,因为它会阻塞当前线程。

例子:

final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
new Thread(new Runnable() {
    @Override
    public void run() {
        allDoneSignal.await();
        mainThreadHandler.post(new Runnable() {
            doSomethingWhenAllDone();
        });
}
}).start()
于 2018-07-30T08:10:46.587 回答