CountDownLatch in Android locking thread

我是研究僧i 提交于 2019-12-11 06:36:16

问题


I've just started playing around with CountDownLatch in my Android app. Currently I am trying to make two Volley requests to my api, and wait until the data has been retrieved and stored before continuing with thread execution.

This is a sample of my code:

    // 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();
    }

The issue is that it doesn't seem to "complete" the countdown and therefore freezes because the latch is never released. I have confirmed that the API requests are working and the onSuccess callback is hit successfully, but the thread hangs.

UPDATE I've just noticed that with the CountDownLatch set to 0, it hits onSuccess, but when I set it to anything greater than 0, it freezes and onSuccess is never called. Seems like something's funky with the threading.


回答1:


Your code is too error prone, you need to call countDown() in a finally block and call it also in onFail otherwise in case of failure your application will freeze for ever. So your code should rather be something like:

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



回答2:


Sorry for the late answer, but if it's still any help to anyone:

You need to do the ".await" in a separate thread because it blocks the current thread.

Example:

final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
new Thread(new Runnable() {
    @Override
    public void run() {
        allDoneSignal.await();
        mainThreadHandler.post(new Runnable() {
            doSomethingWhenAllDone();
        });
}
}).start()


来源:https://stackoverflow.com/questions/38694614/countdownlatch-in-android-locking-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!