在Java中并行迭代单个列表而不重复
我有一个填充了“someObject”的ArrayList。我需要用4个不同的线程(使用Futures和Callables)遍历这个列表。线程将保留它遇到的前5个值对象。我第一次尝试创建一个并行流,但效果不太好。是否有一些明显的事情我没有想到,因此每个线程可以迭代对象,而不可能捕获同一对象两次?您可以使用在Java中并行迭代单个列表而不重复,java,multithreading,parallel-processing,Java,Multithreading,Parallel Processing,我有一个填充了“someObject”的ArrayList。我需要用4个不同的线程(使用Futures和Callables)遍历这个列表。线程将保留它遇到的前5个值对象。我第一次尝试创建一个并行流,但效果不太好。是否有一些明显的事情我没有想到,因此每个线程可以迭代对象,而不可能捕获同一对象两次?您可以使用 class MyRunnable implements Runnable { final List<SomeObject> list; final AtomicIn
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实现Runnable{
最后名单;
最终AtomicInteger计数器;//初始化为0
公开募捐{
while(true){
int index=counter.getAndIncrement();
如果(索引
只要每个
MyRunnable
具有相同的AtomicInteger
引用,它们就不会重复索引您不需要AtomicInteger
或任何其他同步
您应该简单地根据处理线程的数量(其数量也是预先知道的)对列表(其大小是预先知道的)进行逻辑分区,并让每个线程在列表的[from,to]中自己的部分上操作
这就完全避免了对任何同步的需要(即使它只是一个优化的同步,比如AtomicInteger
),这是您应该一直努力实现的(只要它是安全的)
伪码
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);
}
类工作程序实现可运行{
最终处理列表;
受保护的工作程序(列表、int-fromInc、int-toExcl){
//注意,这不允许传递空列表或指定空工作部分,但如果您愿意,您可以放松
//这还隐式检查列表是否为null
预条件.checkArgument(fromInc>=0&&fromInc 先决条件。checkArgument(toExcl>0&&fromInc)我不确定我是否在跟踪这个问题,但可能会将对象分成四个子列表,每个线程一个子列表?