在Java

时间:2016-06-29 23:14:51

标签: java multithreading parallel-processing

我有一个填充了' someObject'的ArrayList。我需要迭代这个列表,有4个不同的线程(使用Futures& Callables)。线程将保留它遇到的前5个有价值的对象。我首先尝试创建一个并行流,但这并没有很好地解决。是否有一些我没想到的显而易见的事情,所以每个线程都可以迭代对象,而不是两次抓取同一个对象?

2 个答案:

答案 0 :(得分:1)

您可以使用AtomicInteger来遍历列表:

class MyRunnable implements Runnable {
    final List<SomeObject> list;
    final AtomicInteger counter; // initialize to 0

    public void run() {
        while(true) {
            int index = counter.getAndIncrement();
            if(index < list.size()) {
                do something with list.get(index);
            } else {
                return;
            }
        }
    }
}

只要每个MyRunnable具有相同的AtomicInteger引用,它们就不会重复索引

答案 1 :(得分:1)

您不需要AtomicInteger或任何其他同步。

您应该根据处理线程的数量(其编号也是预先知道的)在逻辑上对列表进行逻辑分区(其大小是预先知道的),并让它们中的每一个都在其自己的[from,to]部分上运行。列表。

这完全不需要任何同步(即使它只是一个优化的同步,如class Worker<T> implements Runnable { final List<T> toProcess; protected Worker(List<T> list, int fromInc, int toExcl){ // note this does not allow passing an empty list or specifying an empty work section but you can relax that if you wish // this also implicitly checks the list for null Preconditions.checkArgument(fromInc >= 0 && fromInc < list.size()); Preconditions.checkArgument(toExcl > 0 && fromInc <= list.size()); // note: this does not create a copy, but only a view so it's very cheap toProcess = list.subList(fromInc, toExcl); } @Override public final void run() { for(final T t : toProcess) { process(t); } } protected abstract process(T t); } ),这是你应该一直努力的目标(只要它是安全的)。

伪代码

AtomicInteger

<!--<resources>--> <!--<resource>--> <!--<directory>src/main/resources</directory>--> <!--<includes>--> <!--<include>*</include>--> <!--</includes>--> <!--<filtering>true</filtering>--> <!--</resource>--> <!--</resources>--> 解决方案(实际上任何不涉及复制列表的解决方案)一样,此解决方案还假设一旦您将列表移除,将修改列表每个线程和处理已经开始。在处理过程中修改列表将导致未定义的行为。