【问题标题】:Future and asynchronism未来和异步
【发布时间】:2018-05-18 20:37:54
【问题描述】:

我使用了一个外部 api(适用于 Android 的 ESRI API),其中我有一个循环,我为其返回一个类 Future

...
for (Layer layer : layers) {

// ListenableFuture extends Future<V>
final ListenableFuture<FeatureQueryResult> future= gdbFeatureTable.queryFeaturesAsync(query);

future.addDoneListener(() -> {
                try {
                    FeatureQueryResult result = future.get();
...
}

try {
                FeatureQueryResult result = future.get();


    }
    ...

是否可以在 for 循环之后以异步方式启动所有 queryFeaturesAsync 并获取全局结果(result1 + result2 + etc..)? 最好的方法是什么?承诺?线程池执行器?

感谢您的帮助

【问题讨论】:

    标签: android asynchronous futuretask esri-arc-engine


    【解决方案1】:

    如果我使用 CompletableFuture 是最好的方法吗? 我都不懂……

    List<CompletableFuture<FeatureQueryResult>> futures = new ArrayList<>();                
    for (Layer layer : layers) {
        FeatureTable gdbFeatureTable = ((FeatureLayer) layer).getFeatureTable();
        CompletableFuture<FeatureQueryResult>  completableFuture = new CompletableFuture<>();
        ListenableFuture<FeatureQueryResult> future = gdbFeatureTable.queryFeaturesAsync(query);
        future.addDoneListener(() -> {
                            FeatureQueryResult result = future.get();
                            completableFuture.complete(result);
        }
        futures.add(future);
    }
    CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
    

    你有其他解决方案吗?

    感谢您的回复

    【讨论】:

    • 对不起,我以前从未使用过CompletableFuture,在这里无法提供帮助。你的例子看起来太复杂了。我认为,你不应该坚持Future 类型。这只是将结果从一个线程传递到另一个线程的一种方式,仅此而已。还有许多其他方法可以将多个异步任务同步在一起。例如,您也可以使用CountDownLatch
    【解决方案2】:

    我认为方法 queryFeaturesAsync() 内部已经使用 ThreadPoolService,并且使用 ThreadPoolService 从另一个 ThreadPoolService 检索结果是矫枉过正,恕我直言。

    我会推荐你​​使用AsyncTask,因为它是原生的Android SDK工具并且使用起来非常简单:

    AsyncTask<ListenableFuture<FeatureQueryResult>, Integer, List<FeatureQueryResult>> task =
            new AsyncTask<ListenableFuture<FeatureQueryResult>, Integer, List<FeatureQueryResult>>() {
        @Override
        protected List<FeatureQueryResult> doInBackground(ListenableFuture<FeatureQueryResult>[] futures) {
            int counter = 0;
            List<FeatureQueryResult> results = new ArrayList<>();
            for (ListenableFuture<FeatureQueryResult> future : futures) {
                try {
                    results.add(future.get());
                    publishProgress(++counter); // Optional feature
                } catch (ExecutionException | InterruptedException e) {
                    Log.w("Huh?", "Interrupted!");
                }
            }
            return results;
        }
    
        @Override
        protected void onProgressUpdate(Integer... values) {
            notifyMainThreadAboutProgress(values[0]); // Optional feature
        }
    
        @Override
        protected void onPostExecute(List<FeatureQueryResult> featureQueryResults) {
            doSomethingWithResultsInMainThread(featureQueryResults);
        }
    };
    
    ListenableFuture<FeatureQueryResult> future1 = gdbFeatureTable.queryFeaturesAsync(query);
    ListenableFuture<FeatureQueryResult> future2 = gdbFeatureTable.queryFeaturesAsync(another_query);
    ListenableFuture<FeatureQueryResult> future3 = gdbFeatureTable.queryFeaturesAsync(yet_another_query);
    
    task.execute(future1, future2, future3);
    

    我将AsyncTask 作为一个匿名类来缩短示例。在生产环境中,它必须是静态类。

    【讨论】:

    • ok as that identifyTask.execute(futures.toArray(new ListenableFuture[futures.size()]));
    • 可能我和 CompletableFuture 合作你觉得怎么样?
    • 我的示例没有使用ListenableFuture 的功能,例如onDone 回调,但仅使用来自Future 接口的方法get(),我认为CompletableFuture 也实现了它。
    • 我下面带有 CompletableFuture 的示例代码......你怎么看?
    • 我下面带有 CompletableFuture 的示例代码......你怎么看?
    猜你喜欢
    • 1970-01-01
    • 2018-08-01
    • 2018-12-12
    • 2016-05-10
    • 2020-11-06
    • 1970-01-01
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    相关资源
    最近更新 更多