我在下面的代码中面临线程问题。当线程执行runnable对象的Run方法时,它不会打印我期望的数据。
代码1 - 调用代码
Map<String,Object> logData = CPEMethodData.getLogDataMap();
CatalogUpdaterLogger.getLogger().info("6 before new splunk logger log data =" + logData);
CatalogrLogger writer = new CatalogLogger(LogType.INFO,logData,LoggerType.CATALOGUPDATER);
LogPool.INSTANCE.submitTask(writer);//submitting writer which is a runnable object to the queue
//add one more task/writer to the queue in the same method
logData = CPEMethodData.getLogDataMap();
CatalogUpdaterLogger.getLogger().info("11 before 3rd writer=logData "+logData);
CatalogLogger writer2 = new CatalogLogger(LogType.INFO,logData,LoggerType.CATALOGUPDATER);
LogPool.INSTANCE.submitTask(writer2);
在上面的代码中,我检查过CPEMethodData.getLogDataMap()返回的logData与我预期的不同。但是当runnable对象实际执行时,它仍然以相同的数据运行...
代码2 - 使用5个线程创建线程池...
public enum LogPool {
INSTANCE;
private static final int nThreads = 5;
final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
public synchronized void submitTask(Runnable task) {
executor.execute(task);
}
代码3 - 可运行代码
public class CatalogLogger implements Runnable {
protected LogType logType;
protected LoggerType loggerType;
protected Map<String, Object> logData;
public CatalogLogger(LogType logType, Map<String, Object> logData,
LoggerType loggerType) {
this.logType = logType;
this.logData = logData;
this.loggerType = loggerType;
}
public void run() {
System.out.println("running with logData " + logData);
System.out.println(" Thread.currentThread().hashCode() " +Thread.currentThread().hashCode());
switch (loggerType) {
case ORDERPROCESSING:
logData(Logger.getLogger(ORDER_LOG));
break;
case CATALOGUPDATER:
logData(Logger.getLogger(CATALOGUPDATER_LOG));
break;
}
}
以下是CPEmethoddata.getLogData
public class CPEMethodData {
private static ThreadLocal<Map<String, Object>> logDataMap = new ThreadLocal<Map<String, Object>>();
public static Map<String,Object> getLogDataMap() {
return logDataMap.get();
}
public static void setOppParameters(Map<String, Object> inputParams) {
Map<String, Object> oppStatus = logDataMap.get();
if (oppStatus == null) {
oppStatus = new HashMap<String, Object>();
logDataMap.set(oppStatus);
}
oppStatus.put(INPUT_PARAMS, inputParams);
}
@SuppressWarnings("unchecked")
public static Map<String, Object> getOperationParameters() {
Map<String, Object> oppStatus = logDataMap.get();
if (oppStatus != null)
return (Map<String, Object>) oppStatus.get(INPUT_PARAMS);
return null;
}
}
当我运行向队列提交两个runnable的代码1时,我希望在run方法的sysout中看到不同的logData内容,但是当我调试它时,我看到两个执行中的数据相同...似乎第二次运行正在干扰第一次......可以请任何人帮我理解这里的问题。我以为我通过2个不同的CatalogLogger实例并且不应该导致任何问题。也可以有人请建议任何解决方案?
答案 0 :(得分:0)
正如@ReneLink在我的问题评论中写的那样,CPEMethodData.getLogDataMap返回了相同的hashmap实例...所以当线程的run方法被执行时,hashmap的内容被修改了。我创建了深层副本使用Cloner工具的hashmap并将其传递给线程。 感谢@ReneLink向我指出这一点。