Giovanni Far
Giovanni Far

Reputation: 1653

Java multi threading HashMap

I have 1 thread that insert values in my hash map and another thread that just read the value by the hashmap. I don't know why i have problem to read the correct value.

I show to you what i did:
By the main thread i add the value in the hash map:

public class S3Esercizio1 {
    public static void main(final String[] args) {
        final EventSource eventSource = new EventSource();
        final Thread eventSourceThread = new Thread(eventSource);

        // run the thread
        eventSourceThread.start();

        // create and register the EventListeners
        final List<EventListener> allListeners = new ArrayList<>();
        for (int i = 0; i < 20; i++)
            allListeners.add(new EventListener(i, eventSource));

        // Wait untill the other thread finish his job.
        try {
            eventSourceThread.join();
        } catch (final InterruptedException e) {
            // Thread interrotto
        }
    }
}

when is created a new EventListener is called this constructor:

public EventListener(final int id, final EventSource eventSource) {

        eventSource.registerListener(id, this);

        // this sleep simulate the problem 
        try {
            Thread.sleep(4);
        } catch (final InterruptedException e) {
            // Thread interrupted
        }

        this.id = id;
    }

and by the registerListener method i insert the value in the hashmap

public synchronized void registerListener(final int id, final EventListener listener) {
        allListeners.putIfAbsent(id, listener);
    }

In the other thread there is the Hashmap, and by this thread i read the values inside in the hashmap while the main thread (at the same time) insert values in the hashmap:

class EventSource implements Runnable {
    final ConcurrentHashMap<Integer, EventListener> allListeners = 
            new ConcurrentHashMap<Integer, EventListener>();

    @Override
    public void run() {
        for (long i = 0; i < 30000000; i++) {
            final Event e = new Event(i);
            final java.util.Iterator<Integer> it = 
                    allListeners.keySet().iterator(); 

                while(it.hasNext()) {
                    final Integer id = it.next();
                    EventListener listener = allListeners.get(id);
                    listener.onEvent(id, e);
                }
        }
    }

    public synchronized void registerListener(final int id, final EventListener listener) {
        allListeners.putIfAbsent(id, listener);
    }
}

when is called onEvent method:

public void onEvent(final int listenerID, final Event e) {
    if (listenerID != id)
        System.out.println("Inconsistent listener ID" + listenerID + " : "
                + e);
}

it check if i get the correct listner in the hashmap by his id.
And i don't know why is not!

this is the output: i put just some rows... but it continue until the last ID (20):

...
Inconsistent listener ID14 : Event: 3104
Inconsistent listener ID14 : Event: 3105
Inconsistent listener ID14 : Event: 3106
...

This is really strange, because i used a: ConcurrentHashMap so in this way i can read and at the same time edit the hashmap without problem...
where is the problem?

Upvotes: 0

Views: 198

Answers (1)

i.zakhartsov
i.zakhartsov

Reputation: 66

Id assignment must be first in constructor of EventListener. Instance of EventListener has undefined state when passing into another thread. Good luck!

Upvotes: 1

Related Questions