Java列表从列表中的不同线程收集结果

时间:2016-01-26 15:24:22

标签: java multithreading arraylist

我有几个计算线程来创建结果值(对象)。每个帖子完成后,添加'调用结果收集器的方法。 结果收集器是单例,因此只有一种表示形式。

结果收集器内部是一个包含结果对象的列表:

List<TestResult> results = Collections.synchronizedList(new ArrayList<>());

add方法将每个线程的结果添加到列表中:

  public void addResult(TestResult result){
        System.out.println("added " + result.getpValue());
        this.results.add(result);
    }

在计算内容完成后,在线程内调用它。

最大的问题是:完成所有线程后,结果列表为空。正如您在addResult方法中看到的,我为pValue添加了一个print语句。打印出所有结果的p值。

所以看起来线程在不同的列表上工作。尽管收集器类是单例的。

有人要求提供结果收集器的完整代码(Javadoc已删除以修剪大小)

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class ResultCollector {

    private static ResultCollector resultCollector;
    private final List<TestResult> results;

    public static ResultCollector getInstance(){
        if(resultCollector == null){
            resultCollector = new ResultCollector();
        }

        return resultCollector;
    }

    private ResultCollector() {
        results = Collections.synchronizedList(new ArrayList<>());
    }

    public void addResult(TestResult result){
        System.out.println("added " + result.getpValue());
        this.results.add(result);
    }
}

我更新了add方法,打印出当前类的哈希,以确保每个线程都具有相同的: System.out.println("added to" + System.identityHashCode(this) + " count: " +results.size());

输出哈希码对于所有线程是相同的,并且大小增加到预期值。当我在多线程环境之外调用我的toString方法或getter时,哈希码也是一样的。

调用线程:

public IntersectMultithread(...) {

    Set<String> tracks = intervals.keySet();

    for(String track: tracks){

        IntersectWrapper wrapper = new IntersectWrapper(...);
        wrappers.add(wrapper);
        exe.execute(wrapper);
    }

    exe.shutdown();
}

2 个答案:

答案 0 :(得分:3)

同步列表只是列表的包装。实际上,您应该在现代Java中将Concurrent Collections用于此目的;它们实现更智能,更高效的锁定并提供更好的性能。

警告:唯一的同步列表是在写入时复制的列表。所以,如果这是一个问题(即你添加的不仅仅是迭代),那么你的方式很好。)*

您的代码中的错误几乎肯定在您未显示的单例类中。要么你的班级不是真正的单身人士(你是否使用了枚举?这是保证它的好方法),或者你的列表创建比让它更容易混淆。

如果您发布更多代码,我可以使用更多信息更新答案:)。

编辑:我认为您的问题是基于您更新的代码:

exe.shutdown();

您需要等待执行程序完成awaitTermination(),并使用与您正在进行的工作相关的良好超时。

你的线程刚刚开始并立即消失:)

例如:

taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

从这里开始:https://stackoverflow.com/a/1250655/857994

答案 1 :(得分:0)

除了上面的正确答案

是的,exe.shutdown();是问题所在,但线程不会立即死亡,相反它们似乎已经完成了。这就是为什么“添加”方法如果使用打印扩展则打印一切正确。

问题是我的输出是在线程完成计算之前完成的。因此,在线程完成和打印工作后不久,当时没有任何值。