for循环中的并发方法执行

时间:2018-05-14 22:53:07

标签: java concurrency

有以下方法:

public void method(Collection<BigInteger> objectIds) {
    Collection<BigInteger> allObjectIds = new HashSet<BigInteger>(objectIds);
    for(BigInteger objId : allObjectIds) {
        SomeObject obj = getObjectById(objId); // obj.getColour(): red, green or blue
        if(isFirstGroup(obj)) { // the first group
            createInFirstGroup(obj);
        } else { // the second group
            createInSecondGroup(obj);
        }
    }    
}

预计会有很多allObjectIds作为输入。为了获得更好的性能,需要同时执行createInFirstGroupcreateInSecondGroup,并考虑以下条件:

  1. SomeObject类型的所有对象可以分为两组 - 第一组和第二组。所有传入的对象都可以来自第一组,第二组或两者。
  2. SomeObject类有一个字段colour,可以等于'red','green','blue'。具有不同ID的对象可以具有相同的颜色值。因此,具有相同颜色值的这些对象可以在每个组内(第1个,第2个或两个)。在createInFirstGroupcreateInSecondGroup方法中,它们的处理在相同的组和颜色的情况下不应该是并发的。
  3. 例如,以下组合是错误的(x,y对):

    • 线程x,y :(第1组,绿色;第1组,绿色)
    • 线程x,y :(第2组,绿色;第2组,绿色)

    以下组合是正确的:

    • 线程x,y :(第1组,绿色;第2组,绿色)
    • 线程x,y :(第1组,绿色;第1组,红色)

    将描述的public void method(Collection<BigInteger> objectIds)方法(其for-loop部分)移植到并发中的正确方法(可能有一些合适的模式)是什么,提供最佳线程数和任务分配(考虑到所描述的条件) )?

    提前谢谢!

1 个答案:

答案 0 :(得分:0)

我对你的约束并不是很清楚,但是一种通用的方法是通过队列连接的管道。您可以使用阻塞队列来应用反压。以下是“actor”的灵感,其中每个actor都是单线程接收阻塞队列并发布到输出队列,但源和接收器除外。您可以根据此实现整个管道,在源和接收器之间进行协调,以便接收器知道何时完成。

  • 来源 - &gt;收集&amp;写objectIds - &gt;到队列
  • &lt; - getObjectById线程从先前读取并写入 - &gt;输出队列
  • &lt; - 在组线程中创建,检查第一个/第二个并创建 - &gt;写入输出
  • &lt; - 最终接收器从前2个输出读取