我有几个计算线程来创建结果值(对象)。每个帖子完成后,添加'调用结果收集器的方法。 结果收集器是单例,因此只有一种表示形式。
结果收集器内部是一个包含结果对象的列表:
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();
}
答案 0 :(得分:3)
同步列表只是列表的包装。实际上,您应该在现代Java中将Concurrent Collections用于此目的;它们实现更智能,更高效的锁定并提供更好的性能。
警告:唯一的同步列表是在写入时复制的列表。所以,如果这是一个问题(即你添加的不仅仅是迭代),那么你的方式很好。)*
您的代码中的错误几乎肯定在您未显示的单例类中。要么你的班级不是真正的单身人士(你是否使用了枚举?这是保证它的好方法),或者你的列表创建比让它更容易混淆。
如果您发布更多代码,我可以使用更多信息更新答案:)。
编辑:我认为您的问题是基于您更新的代码:
exe.shutdown();
您需要等待执行程序完成awaitTermination(),并使用与您正在进行的工作相关的良好超时。
你的线程刚刚开始并立即消失:)
例如:
taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
答案 1 :(得分:0)
除了上面的正确答案
是的,exe.shutdown();
是问题所在,但线程不会立即死亡,相反它们似乎已经完成了。这就是为什么“添加”方法如果使用打印扩展则打印一切正确。
问题是我的输出是在线程完成计算之前完成的。因此,在线程完成和打印工作后不久,当时没有任何值。