更新:這是一個靜態的深埋在一些代碼中,它僅用於幾個指令。謝謝大家的建議。Java HashMap在某些線程中有時會返回錯誤的值
我們沒有在線程之間使用一個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();
}
}
}
}
(編輯格式代碼)
關鍵是什麼?一個簡短但完整的程序展示問題將*真正*幫助... – 2012-02-22 22:23:52
什麼類型的價值可能也是相關的。這些值是否可能包含一個被引用並在其他地方修改過的對象? – VeeArr 2012-02-22 22:36:40
請添加一些示例代碼。 – 2012-02-22 22:44:40