Java保证回调顺序执行

标签 java android multithreading asynchronous volatile

如何保证 Android 上特定代码的执行?

我有一个异步回调,done,它在 Parse api 查询完成后在另一个线程中执行,这是代码

Init() {
    ParseQuery<ParseObject> query = ParseQuery.getQuery("MyTable");
    query.getInBackground("ObjectID", new GetCallback<ParseObject>() {
        public void done(ParseObject object, ParseException e) {
             // [ ... some code ... ] <----------.
        } //                                     |
    }); //                                       |
    // I'd like this is executed after this -----'
}

所以我尝试了这个,但没有成功,当尝试第二次获取信号量时它会阻塞

private final Semaphore available = new Semaphore(1, true);
Init() {
    try {
        available.acquire();
        ParseQuery<ParseObject> query = ParseQuery.getQuery("MyTable");
        query.getInBackground("ObjectID", new GetCallback<ParseObject>() {
            public void done(ParseObject object, ParseException e) {
                // [ ... code ... ]
                available.release();
            }
        });
        available.acquire(); // waits till release
        available.release();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

是否是因为信号量在未获取信号量的线程中被释放?如何解决这个问题?

但是,我也尝试了这种解决问题的虚拟方法

private static volatile Boolean available = false;
Init() {
    available = false;
    ParseQuery<ParseObject> query = ParseQuery.getQuery("MyTable");
    query.getInBackground("ObjectID", new GetCallback<ParseObject>() {
        public void done(ParseObject object, ParseException e) {
            // [ ... some code ... ]
            available = true;
        }
    });
    while (available == false);
}

但是它不起作用,它在循环内阻塞,并且回调没有被执行。通过删除此循环中的循环,回调将被执行,因此问题一定与循环有关

最佳答案

我通常用CountDownLatch来做到这一点。据我所知,它也存在于 Android API 中( here ),因此您可以使用它:

Init() {
    ParseQuery<ParseObject> query = ParseQuery.getQuery("MyTable");
    final taskFinishedLatch = new CountDownLatch(1);
    query.getInBackground("ObjectID", new GetCallback<ParseObject>() {
        public void done(ParseObject object, ParseException e) {
             try {
                 // [ ... some code ... ]
             } finally {
                 taskFinishedLatch.countDown();
             }
        } //                                     |
    }); //                                       |
    taskFinishedLatch.await();
    // alternatively, you can use timeouts, e.g.
    // taskFinishedLatch.await(5,  TimeUnit.SECONDS);
}

这里只有一个警告:您需要确保 taskFinishedLatch.countDown(); 正在被调用。这就是为什么我添加了 try {...} finally {...} block 。

在这种情况下,这还不够。您需要处理查询未调用 done 回调的情况。 IE。有error回调吗?您可以使用时间超时,例如 taskFinishedLatch.await(5, TimeUnit.SECONDS),但这会使行为有点模糊。

关于Java保证回调顺序执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43837737/

相关文章:

安卓工作室 : How to delete crashlytics plugin

c# - winforms应用程序中的多线程

java - 如何在不同的线程中做不同的事情?

java - 如何使 ScheduledExecutorService 在其计划任务被取消时自动终止

java - 如何在 Android 中对组和子级可扩展 ListView 进行排序?

java - 模式/匹配器不适用于换行符

java - MediaExtractor.setDataSource 抛出 IOException "failed to instantiate extractor"

java - 完成 future : Unhandled exception type ExecutionException

android - 从 NDK 代码访问应用程序数据路径

java - XSL 使用参数 for-each