当前位置: 首页 > 知识库问答 >
问题:

并行排序顺序

金晗日
2023-03-14

我正在实现一个分页器(在Java),它应该允许并行访问。

我有以下测试用例(测试在Groovy中,带有Spock):

def 'parallel, two pages'()
{
    when: 'a sorted range from 0 to 6'
    def fetcher = new IntegerRangePageFetcher(6)

    and: 'a spliterator with a page size of 5'
    def spliterator = new PagedSpliterator(fetcher, 5)

    and: 'a stream with the given range is collected to a list'
    def result = StreamSupport
            .stream(spliterator, true)
            .collect(Collectors.toList())

    then: 'the sort order is obeyed'
    expect result, contains(0, 1, 2, 3, 4, 5)
}

此testcase失败,出现以下错误:

Condition not satisfied:

expect result, contains(0, 1, 2, 3, 4, 5)
|      |
false  [5, 0, 1, 2, 3, 4]

Expected: iterable containing [<0>, <1>, <2>, <3>, <4>, <5>]
     but: item 0: was <5>

拆分器具有特性()

return IMMUTABLE | ORDERED | SIZED | SUBSIZED | NONNULL;

当我不使用并行时,代码可以工作。所以我不理解ordered:

  • 如果设置了,流框架是否应该保证顺序,并且应该在使用并行生成的块时对结果进行排序?如果是,为什么不在我的情况下排序?
  • 还是我的trysplit实现中有错误,必须按照给定的顺序拆分?(当前我在打开页面的中间进行拆分,0-mid保留在当前的拆分器中,mid-end保留在新创建的拆分器中)
  • 还是应该在collection()之前调用sort()因为框架根本不保证任何顺序?

---根据反馈进行更新---

谢谢你的回答,我的代码中有两个逻辑错误。首先,请求的代码段:

@Override
public Spliterator<T> trySplit()
{
    // first query
    if (pageIterator == null) {
        pageIterator = pageFetcher.fetchNextPage(paginationInfo);
    }

    // delegate split decision
    var newPaginationInfo = paginationInfo.split();
    if (newPaginationInfo == null) {
        log.info("* Spliterator returns null");
        return null;
    }

    // now we split
    var newSpliterator = new PagedSpliterator<>(pageFetcher, newPaginationInfo);
    return newSpliterator;
}

public PaginationInfo split()
{
    // when open range or nothing left we don't split
    if ((endElementIndex == -1) || !hasNextPage()) {
        return null;
    }

    // calculate the splitting position
    var firstHalfPages = (getEndPageIndex() - getNextPageIndex()) / 2;
    var midElementIndex = (getNextPageIndex() + firstHalfPages) * pageSize;

    // create an additional PaginationInfo and set the ranges according to the split position
    var newPaginationInfo = new PaginationInfo(this);
    newPaginationInfo.firstElementOnNextPageIndex = midElementIndex;
    newPaginationInfo.nextElementIndex = midElementIndex;

    endElementIndex = midElementIndex;

    return newPaginationInfo;
}

第一个错误:

新创建的拆分器被设置为第二个半范围,而不是第一个半范围。我在文档中读到了关于前缀的内容,但它对我来说感觉非常笨拙。我按页面大小拆分以有多个并行请求。在开始时(第一个spliterator实例),我必须获取第一个页面以获得页面和元素计数器。因此,为了解决顺序问题,我必须将从第一个拆分器获取的数据分发到第二个拆分器以服从顺序,这对我来说感觉很奇怪,也不直观。

第二个错误:

    // first query
    if (pageIterator == null) {
        pageIterator = pageFetcher.fetchNextPage(paginationInfo);
    }

所有后续创建的拆分器都将从框架接收EstimateSize()TrySplit()调用。在此调用期间,当前我提取一个页面,但这将阻止并行性,该提取必须在TryAdvance()调用的稍后时间发生。

我会实现这些更改,然后再回到你身边。

共有2个答案

壤驷旭
2023-03-14

trysplit的文档中可以看到:

如果对此拆分器进行排序,则返回的拆分器必须覆盖元素的严格前缀。

您的实现:

...0-MID保留在当前的分裂器中,mid-end保留在新创建的分裂器中

你可以从这里连接适当的点。

于飞飙
2023-03-14

是的,你的试玩中有个漏洞。spliterator.trysplit的文档指定,如果您具有ORDERED特性,则返回的spliterator必须包含元素的前缀。切换返回的拆分器和拆分器的剩余内容。

 类似资料:
  • 我有一个记录课程: 我创建了一个包含很多记录的大列表。只有第二个和第五个值,即i/10000和i,稍后分别由getter使用。 请注意,前10000条记录的类别2为0,接下来的10000条记录的类别1等,而值1按顺序为0-114999。 我创建了一个既并行又排序的流。 我有一个ForkJoinPool,它维护8个线程,这是我电脑上的内核数。 我使用这里描述的技巧将流处理任务提交给我自己的,而不是常

  • 对于一项作业,我必须要求学生人数。提示用户输入学生的lastname和分数,然后按降序对分数排序并显示。我已经做了所有这些,但不知道如何排序的名字,如果他们有相同的分数。 约翰33岁 亚当33 菲尔22 我无法得到所需的输出。我通常能解决这类问题,但这个问题让我分崩离析…请救命!

  • 问题内容: 我正在尝试通过sequelize从数据库中输出所有对象列表,如下所示,并希望在我在where子句中添加id时对数据进行整理。 但是问题是渲染后,所有数据按如下进行整理。 正如我发现的那样,它既没有按ID也没有按名称排序。请帮我解决。 问题答案: 在序列化中,您可以轻松添加order by子句。 看看我如何添加对象数组? 编辑: 一旦在诺言中收到对象,您可能必须订购这些对象。查看有关根据

  • 问题内容: 假设我有以下代码: 输出是相同的线程名称,因此这里没有任何好处-我的意思是,只有一个线程可以完成所有工作。 里面是这段代码: 我知道如果“外部”流是并行的(可能会阻塞),则强制该属性,“外部”将不得不等待“ flatMap”完成,反之亦然(因为使用了相同的公共池),但是为什么 总是 强迫那个? 那是在以后的版本中 可能会 更改的事情之一吗? 问题答案: 有两个不同方面。 首先,只有一个

  • 主要内容:1 Java8 并行数组排序的介绍,2 Java8 并行数组排序的方法,3 Java8 并行数组排序案例1,4 Java8 并行数组排序案例21 Java8 并行数组排序的介绍 Java在Array类中提供了一个新的附加功能,该功能用于对数组元素进行并行排序。java.util.Arrays包中添加了新方法,该方法使用JSR 166 Fork / Join并行公共池对数组进行并行排序。被称为parallelSort() ,并且对所有原始数据类型和Comparable对象都进行了重载。

  • 问题内容: 因此,在数据库中,我存储了乐器名称(以及其他各种属性)。假设它是主键,并且是唯一键。 在PHP脚本中,我按其乐器类选择项,如下所示: 结果表: 这使我可以仅通过查询“萨克斯管”来选择整个乐器系列,例如“高音萨克斯管”,“中音萨克斯管”等。 在该特定示例中,结果按其ID排序(您可以假定其为auto_incremented)。更理想的是按字母顺序排序,是吗? 这工作正常,但作为音乐人,他们