这是编写异步迭代器的正确方法吗?

时间:2018-07-04 05:08:07

标签: java

您好:我想知道如何编写异步表迭代器。假设输入表由许多行组成,并且在接收到该表时,该表为序列化格式。 收到表后,将调用迭代器以逐行检索一行。

它通过以下方式执行读取和反序列化: 1)它首先读取有关行大小的整数并将其反序列化。 2)然后,读取并反序列化该行的内容,其中, 一种。通过调用in.readint()首先准备好时间戳 b。然后读取并反序列化该行的每个键, C。然后,读取并反序列化有关非关键列的位图字符串。 d。然后调用in.readint()读取并反序列化表示非键列数的整数,然后读取并反序列化每个非键列。 3)最后,它读取并反序列化文件结尾标记,该标记指示是否到达文件结尾。

最后,它返回反序列化的行。

这是代码

enter code here
public Row next() {
/* It first reads the integer about the size of the row and 
deserialize it. */
int size = in.readInt();         
/*Then it reads and deserialize the contents of the row*/
Row row = Row.deserialize(descriptor, in);

/*Finally it reads and deserializes the file end marker, which 
indicates if the end of the file is reached.*/
int signal = in.readInt();
if (signal == FILE.END) {
    file_end = true;
    return row;
}
return row;
}

public Row deserialize(DataInput in) throws IOException {
/*timestamp is first ready by calling in.readint()*/
long timestamp= in.readLong();

Object[] Key = new Object[KeyColumns().size()];
Map<Column, Object> columns = new HashMap<>();

/*then each key of the row is read and deserialized */
int i = 0;
for (Column<?> col : KeyColumns()) {
    Key[i++] = col.type.deserialize(in);
}

/* then the bitmap string about the non-key columns is read and 
deserialized. */
int bitstring= in.readInt();

/*then calls in.readint() to read and deserialize the integer which
represents the number of non-key columns, and then it reads and 
deserialize each non-key column.*/

i = 0;
for (Column<?> col : rowColumns()) {
    if ((bitstring & (1 << i)) != 0){
    columns.put(col, col.type.deserialize(in));
}
    i++;
    }
    return new Row(timestamp, Key, columns);
}

要将这个迭代器转换为异步迭代器,我正在考虑在Java 8中使用CompletableFuture并将读取结果与反序列化脱钩。也就是说,使用单独的thend来处理读数,如下面的

public Row next() {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            int size= 0;
            try {
                size = in.readInt();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        Row row = Row.deserialize(descriptor, in);
        int signal = in.readInt();

        if (signal == FILE.END) {
            file_end = true;
            return row;
        }
        return row;
}

但是在我看来,因为这样做的线程  “ size = in.readInt();”和执行“ Row row = Row.deserialize(descriptor,in);”的主线程共享同一流。他们需要一个接一个地发生。仍然没有实现并行性。 有没有更好的方法来实现此异步迭代器? 谢谢。

1 个答案:

答案 0 :(得分:1)

首先,您的核心是阻塞资源(DataInput)。因此,无论您做什么,都将在阅读DataInput时保持同步。

在Java 8中,我肯定会使用流来实现这一点。看到以下问题:

  

How to implement a Java stream?

最简单的方法是实现Spliterator并使用StreamSupport.stream(...)用它创建一个流。在Spliterator中,您主要只需要实现tryAdvance方法,该方法基本上就是您的“读取下一行”例程。在那里,您需要同步来自DataInput的读取。

拥有Stream<Row>后,您将可以使用mapforEach等对它应用不同的功能。

要实现并行性,您需要在trySplit中实现Spliterator方法。问题来了:如果您无法并行读取DataInput,则拆分不会带来太多收益。但是我仍然认为为相同的Spliterator创建DataInput的新实例并在读取时使其同步是有意义的。读取不会并行化,但可以(在并行流中)进行进一步处理。