Java多线程HashMap

标签 java multithreading

我有 1 个线程在 HashMap 中插入值,另一个线程仅通过 HashMap 读取值。我不知道为什么我无法读取正确的值。

我向你展示我做了什么:
通过主线程,我在 HashMap 中添加值:

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
        }
    }
}

当创建一个新的EventListener时,调用这个构造函数:

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

通过 registerListener 方法,我将值插入到 HashMap 中

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

在另一个线程中有 HashMap ,通过这个线程,我读取 HashMap 中的值,而主线程(同时)在 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);
    }
}

什么时候调用onEvent方法:

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

它检查我是否通过他的 id 在 HashMap 中获得了正确的监听器。
我不知道为什么不是!

这是输出:我只输入了一些行...但它会一直持续到最后一个 ID (20):

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

这真的很奇怪,因为我使用了:ConcurrentHashMap,这样我就可以毫无问题地读取并同时编辑 HashMap ...
问题出在哪里?

最佳答案

Id 分配必须首先出现在 EventListener 的构造函数中。 EventListener 的实例在传递到另一个线程时具有未定义的状态。祝你好运!

关于Java多线程HashMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22750989/

相关文章:

java - 如何输入数字列表并将其分配给变量

java - 如何将超时从一个 FutureTask 传播到另一个由其 Callable 使用的依赖任务?

java - Spring Security 使用模型属性来应用角色

java - 如何使用输入大小修饰符打印长类型值?

java - 转换为 Dalvik 格式失败 : Unable to execute dex: Multiple dex files are defined

windows - 使用太多静态链接的 CRT 解决 fls 限制?

java - 将 room 中的行插入到主线程后如何获取插入的行 id

java - 随着线程数的增加,向 HDD 写入文件变得更慢

Java线程练习: Access control to a limited resource not working

iphone - 为每个新的 NSOperation 或线程创建一个新的 NSManagedObjectContext 是否足够?