Piyush
Piyush

Reputation: 388

Nullpointer exception while updating a global Hashmap with separate Threads

I am getting a Null pointer exception in my Hashmap which is a global variable and is getting updated by separate threads. While debugging all threads are running fine and updating the Hashmap but when i execute program one thread throws Null pointer.

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();

		

	}

}

The ConnectP class looks like:

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();
        }

    }

}

The exception I am getting is

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)

I will be thankful for help. If there is some efficient way to do same, will be highly appreciated.

Upvotes: 1

Views: 986

Answers (2)

Gray
Gray

Reputation: 116938

I am getting a Null pointer exception in my Hashmap which is a global variable and is getting updated by separate threads.

HashMap is not a synchronized class. If multiple threads are updating the map at the same time then it is very possible that their memory view of this map will get out of sync which could cause NPEs, infinite loops, or other bad things.

<tldr> The easiest way to do this is to use the ConcurrentHashMap class which takes care of synchronization for you. </tldr>

// thread-1   
RunEngine.queue_map.put(pub_id, publisherqueue);
...
// thread-2
RunEngine.queue_map.get(pub_id).size()

Right. One thread looks to be putting and another is getting. When you do this in multiple threads then you need to worry about:

  • Memory visibility to ensure the changes to the map in one thread are seen by other threads.
  • Locking to ensure that two threads aren't making changes to the map at the same time and their updates clash.

Basically each thread has a local memory cache per-processor that allows it to access cached results efficiently without having to get everything from main memory. So when thread-1 updates the map, it may only do so in it's cache. If thread-2 then gets from the map it might see none of of the updates or, worse, a partial update of the map depending on the virtual memory details. If both threads are updating the map then the one that flushes its memory cache to main memory will overwrite the updates made by the other one.

This is true with any object that you are sharing between threads. Only immutable objects with final fields can be shared between threads without worry. Otherwise you need to use the volatile or synchronized keywords to ensure they are shared appropriately. To do this correctly is pretty difficult and requires a lot of experience with Java threads and memory synchronization constructs.

The Java tutorial about synchronization may be a good place to get started.

Upvotes: 1

Ramandeep Kaur
Ramandeep Kaur

Reputation: 111

You can use concurrent HashMap for Thread Safety.

Upvotes: 0

Related Questions