链完成同步和异步

时间:2018-11-29 14:42:35

标签: android rx-java

我有一个完整列表,默认情况下,我使用concat / andThen运算符一个接一个地运行它们。 有时,我希望部分可完成对象并行运行,并且在完成所有操作后继续执行列表中的下一个可完成对象。 我试图通过以下代码实现这一目标:

    var completable =
            getAsyncCompletables()?.let {
                it
            } ?: run {
                completables.removeAt(0).getCompletable()
            }
        while (completables.isNotEmpty()) {
            val nextCompletable = getAsyncCompletables()?.let {
                it
            } ?: run {
                completables.removeAt(0).getCompletable()
            }
            completable = nextCompletable.startWith(completable)
        }
        completable
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(AndroidSchedulers.mainThread())
            .subscribe()

我使用以下代码来检测异步可完成对象:

 private fun getAsyncCompletables(): Completable? {
    if (completables.size < 2 || !completables[1].async) {
        return null
    }
    var completable = completables.removeAt(0).getCompletable()
    while (completables.isNotEmpty() && completables[0].async) {
        completable = completable.mergeWith(completables.removeAt(0).getCompletable())
    }
    return completable
}

所有工作正常,除了一件事,尽管我使用了“ startWith”,但最后一个可完成的操作没有触发。 我也尝试过“ concatWith”和“ andThen”,但结果相同。

1 个答案:

答案 0 :(得分:1)

如果不看更多代码,特别是#include <stdio.h> #include <stdlib.h> #include <string.h> extern size_t read_line(FILE *file, char **line); typedef enum Category { OBJECT, DESCRIPTION, TYPE } Category; Category next_category(const Category category) { return (Category) ((category + 1) % 3); } int main(void) { char *object[3]; char *description[3]; char *type[3]; size_t counter = 0; FILE *file = fopen("example.csv", "r"); char *line = NULL; size_t length = 0; while ((length = read_line(file, &line)) > 0 && counter < sizeof(object)) { Category token_category = 0; char *next_token = strtok(line, ";"); while (next_token != NULL) { size_t token_length = strlen(next_token); switch (token_category) { case OBJECT: object[counter] = calloc(token_length, sizeof(char)); memcpy(object[counter], next_token, token_length); break; case DESCRIPTION: description[counter] = calloc(token_length, sizeof(char)); memcpy(description[counter], next_token, token_length); break; case TYPE: type[counter] = calloc(token_length, sizeof(char)); memcpy(type[counter], next_token, token_length); break; } // Read the next token from the same string next_token = strtok(NULL, ";"); token_category = next_category(token_category); } free(next_token); free(line); ++counter; } fclose(file); printf("Objects: %s, %s, %s\n", object[0], object[1], object[2]); printf("Descriptions: %s, %s, %s\n", description[0], description[1], description[2]); printf("Types: %s, %s, %s\n", type[0], type[1], type[2]); return 0; } 的工作以及async的数据结构是什么,很难回答。但是,无论这些值如何,您正在寻找的答案很可能都是相似的。您可能要使用completablesCompletable.merge(...)

根据文档:

Completable.mergeArray(...)

为了实现并行执行,您将需要使用新线程调用列表/数组/集中的 /** * Returns a Completable instance that subscribes to all sources at once and * completes only when all source Completables complete or one of them emits an error. * ... */ 的每个Completable。可以使用subscribeOn或通过Schedulers.newThread()之类的共享池来完成。

为了确定,我进行了测试。这是代码。

Schedulers.io()

这是输出。

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...

    val completeOne = Completable.fromAction {
        Timber.d("Completable #1 running on ${Thread.currentThread().name}")
    }

    val completeTwo = Completable.fromAction {
        Timber.d("Completable #2 running on ${Thread.currentThread().name}")
    }

    val completeThree = Completable.fromAction {
        Timber.d("Completable #3 running on ${Thread.currentThread().name}")
    }

    val completables = listOf(completeOne, completeTwo, completeThree).map { CompletableWrapper(it) }
    val asyncCompletables = completables
        .asSequence()
        .filter { it.async }
        .map { it.getCompletable().subscribeOn(Schedulers.io()) }
        .toList()

    Completable.merge(asyncCompletables)
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe({
            Timber.i("Completed all completables")
        }, Timber::e)
}

class CompletableWrapper(
    private val completable: Completable,
    val async: Boolean = true
) {
    fun getCompletable() = completable
}

如您所见,它将在池中的新线程上运行每个可完成对象,并且仅在每个可完成对象完成之后才调用全部完成的操作。

See here for the documentation on Completable.merge/mergeArray