更新:这是一个静态埋藏在某些代码中,仅用于几条指令。谢谢大家的建议。
我们没有跨线程使用一个HashMap(是的,这有很多原因)。每个线程都有自己的HashMap。
我们有一个从Thread扩展的类。在Thread.run()中,我们创建一个HashMap,在其中设置一个键/值对,并将该HashMap传递给一个方法。该方法从HashMap中检索值,将其插入到字符串中,然后返回字符串。
有时返回的字符串具有不同的值(仍在Thread.run()中)。这仅发生在具有3个以上物理内核的硬件上。它只发生了两次(在我们添加日志记录之前,帮助我们找到当然发生的事情)。
知道为什么会这样。
更新:这是完整的代码。 ProcessTxt是从HashMap中提取值并将其放入字符串中的内容。
import java.io.*;
import java.util.HashMap;
import junit.framework.TestCase;
import net.windward.datasource.dom4j.Dom4jDataSource;
import net.windward.xmlreport.ProcessReport;
import net.windward.xmlreport.ProcessTxt;
/**
* Test calling from multiple threads
*/
public class TestThreads extends TestCase {
private static String path = ".";
// JUnit stuff
public TestThreads(String name) {
super(name);
}
// Get logging going - called before any tests run
protected void setUp() throws Exception {
ProcessReport.init();
}
// this is not necessary - called after any tests are run
protected void tearDown() {
}
private static final int NUM_THREADS = 100;
private boolean hadWithVarError = false;
/**
* Test that each thread has unique variables.
*/
public void testRunReportsWithVariables() throws Exception {
// run 10 threads
ReportThreadWithVariables[] th = new ReportThreadWithVariables[NUM_THREADS];
for (int ind = 0; ind < NUM_THREADS; ind++) {
th[ind] = new ReportThreadWithVariables(this, ind);
th[ind].setName("Run " + ind);
}
for (int ind = 0; ind < NUM_THREADS; ind++)
th[ind].start();
boolean allDone = false;
while (!allDone) {
Thread.sleep(100);
allDone = true;
for (int ind = 0; ind < NUM_THREADS; ind++)
if (th[ind].isAlive())
allDone = false;
}
assertTrue(!hadWithVarError);
}
public static class ReportThreadWithVariables extends Thread {
private TestThreads obj;
private int num;
public ReportThreadWithVariables(TestThreads tt, int num) {
obj = tt;
this.num = num;
}
public void run() {
try{
System.out.println("starting " + num);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ProcessTxt pt = new ProcessTxt(new FileInputStream(new File(path, "Thread_Test.docx")), out);
pt.processSetup();
// don't use order1.xml, but need a datasource.
Dom4jDataSource datasource = new Dom4jDataSource(new FileInputStream(new File(path, "order1.xml")));
HashMap map = new HashMap();
map.put("num", new Integer(num));
datasource.setMap(map);
pt.processData(datasource, "");
pt.processComplete();
String result = out.toString().trim();
System.out.println("complete " + num + ", result = " + result);
String expected = "Number: " + num;
if (!result.equals( expected ))
obj.hadWithVarError = true;
assertEquals(expected, result);
} catch (Throwable e) {
obj.hadWithVarError = true;
e.printStackTrace();
}
}
}
}
(编辑格式代码)
答案 0 :(得分:1)
鉴于缺乏代码并仅基于已编写的内容,我将假设某些内容为static
。也就是说,沿着该行的某处,静态成员被存储到/写入。
答案 1 :(得分:0)
num不可变,其他变量(字符串,映射)是本地的,因此ReportThreadWithVariables看起来是线程安全的。在我看来,问题在于调用外部对象而不是您发布的内容。 您使用的类是否记录为线程安全?
例如,javadoc of the processData method表示对于您似乎正在执行的相同数据源(同一文件名),不应多次调用它。
ps :(不相关)你可以使用CountDownLatch而不是while循环。