我在Hashmap中得到了一个Null指针异常,这是一个全局变量,并通过单独的线程进行更新。在调试时,所有线程都可以正常运行并更新Hashmap,但是当我执行程序时,一个线程会抛出Null指针。
public class RunEngine {
/**
* @param args
*/
public static Map<Integer, List<Event>> queue_map = new HashMap<Integer, List<Event>>();
public static void main(String[] args) {
/*
* check file present in data set folder or not , if present fetch the file name
* and store then in a list
*/
File folder = new File(ConfigurationParameters.FOLDER_PATH);
File[] listOfFiles = folder.listFiles();
/* Create a thread pool for number of Publishers which you want to initialise */
ThreadPoolExecutor executor = new ThreadPoolExecutor(ConfigurationParameters.P_NUMBER,
ConfigurationParameters.P_NUMBER + 3, 100, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy()); // P_NUMBER = 2
for (int i = 1; i <= ConfigurationParameters.P_NUMBER; i++) {
ConnectP conn = new ConnectP(
ConfigurationParameters.FOLDER_PATH + "\\" + listOfFiles[i - 1].getName(),
ConfigurationParameters.DISTRIBUTION_RANDOM, i);
executor.execute(conn);
}
executor.shutdown();
}
}
ConnectP类如下:
public class ConnectP implements Runnable {
private String file_path;
private String distribution_constant;
private int pub_id;
/**
* @param file_path
* @param distribution_constant
*/
public ConnectP(String file_path, String distribution_constant, int pub_id) {
super();
this.file_path = file_path;
this.distribution_constant = distribution_constant;
this.pub_id = pub_id;
}
public void streamevent(List<Event> eventlist, String distributionconstant)
throws InterruptedException {
if (distributionconstant.matches(ConfigurationParameters.PUBLISHER_DISTRIBUTION_RANDOM)) {
List<Event> publisherqueue = new ArrayList<>();
RunEngine.queue_map.put(pub_id, publisherqueue);
for (Event event : eventlist) {
long start = System.currentTimeMillis(); // get present system timestamp
event.setTimeStamp(start);
publisherqueue.add(event); // add to publisher queue
Random rand = new Random();
int value = rand.nextInt(1000); // add a random seed for streaming
Thread.sleep(value); // sleep the process for that value
System.out.println("Publisher " + String.valueOf(pub_id) + " : " + RunEngine.queue_map.get(pub_id).size()); **(throwing exception line 68)**
}
}
}
// function to connect to source file and return list of publication event
public List<Event> connectsource(String filepath) {
// return list after reading file
return list;
}
@Override
public void run() {
// TODO Auto-generated method stub
List<Event> event = this.connectsource(file_path); // connect to source
try {
System.out.println("THREAD " + String.valueOf(pub_id)+ " Initiated");
this.streamevent(event, distribution_constant);**(throwing exception line 121)**
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
我得到的例外是
Exception in thread "pool-1-thread-1" java.lang.NullPointerException
at org.test.event.ConnectP.streamevent(ConnectP.java:68)
at org.test.event.ConnectP.run(ConnectP.java:121)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
感谢您的帮助。如果有一些有效的方法可以做到这一点,将不胜感激。
答案 0 :(得分:1)
我在Hashmap中得到了一个Null指针异常,这是一个全局变量,并且正在通过单独的线程进行更新。
HashMap
不是同步类。如果多个线程同时更新该映射,则它们的该映射的内存视图很可能会不同步,这可能导致NPE,无限循环或其他不良情况。
ConcurrentHashMap
类,该类为您处理同步。
// thread-1
RunEngine.queue_map.put(pub_id, publisherqueue);
...
// thread-2
RunEngine.queue_map.get(pub_id).size()
对。一个线程看起来像在推销,而另一个线程正在变得。当您在多个线程中执行此操作时,您需要担心:
基本上,每个线程在每个处理器上都有一个本地内存缓存,使它可以高效地访问缓存的结果,而不必从主内存中获取所有内容。因此,当线程1更新地图时,它只能在缓存中这样做。如果然后从线程2获取线程2,则它可能看不到任何更新,或者更糟的是,根据虚拟内存详细信息,该映射的部分更新。如果两个线程都在更新映射,则将其内存缓存刷新到主内存的那个将覆盖另一个线程所做的更新。
对于在线程之间共享的 any 对象,这是正确的。只有具有最终字段的不可变对象可以在线程之间共享,而不必担心。否则,您需要使用volatile
或synchronized
关键字以确保正确共享它们。要正确地做到这一点非常困难,并且需要Java线程和内存同步结构方面的丰富经验。
Java tutorial about synchronization可能是入门的好地方。
答案 1 :(得分:0)
您可以将并发HashMap用于线程安全。