在线程中同步Hashmap

时间:2013-10-21 20:41:35

标签: java multithreading hashmap executorservice concurrenthashmap

我在处理同步idMap时遇到了一些问题。此映射用于两个同时运行的run()方法。在第一个run()方法中,我只是将事件id值映射到响应id(key)。在第二个run()方法中,我希望获得具有相同响应ID(键)的事件id(值)。但是,有时某些事件ID存在,有时无法获得。该程序编译得很好,但我不是线程专家,我相信线程导致这个idMap不同步。我的问题很简单,我如何让idMap顺利工作并获得我想要的事件ID?

ConcurrentHashMap<String, String> idMap = new ConcurrentHashMap<String, String>();
ConcurrentHashMap<String, ExecutorService> executors = new ConcurrentHashMap<String, ExecutorService>();

private final class ResponderTask implements Runnable {
    private ResponderTask(Event event) {
        this.event = event;
    }
    // 1st run()    
    public void run() {
        idMap.put(response.getId(), event.getId()); 
    }
}//end ResponderTask 

private final class QuoteTask implements Runnable {
    //constructor
    //2nd run() 
    public void run() {
        IdMap.get(response.getId());
    }
}//end QuoteTask

public void onResponse(final Response response) {

    ExecutorService quoteExecutor = executors.get(response.getId());
    if (quoteExecutor == null) {
        quoteExecutor = Executors.newSingleThreadExecutor();                
        executors.put(event.getId(), quoteExecutor);            
    }
    quoteExecutor.execute(new ResponderTask(event));
}

1 个答案:

答案 0 :(得分:0)

  

然而,有时会出现一些事件ID,有时无法获得。该程序编译得很好,但我不是线程专家,我相信线程导致这个idMap不同步。

idMap是一个ConcurrentHashMap,它被许多人正确地同步并高度使用和测试。如果你在查找时id不在地图中,那么它还没有放在那里。如果您对代码有更多解释,我们可能会发现您的问题。

例如,我看不到response对象的来源。 ResponseTask是否可能正在处理您所期望的不同响应? responseevent应该是同一个参数吗?

  

我的问题很简单,我怎样才能使idMap顺利运行并获得我想要的事件ID?

要弄清楚程序的正确操作应该是多么困难。如果您正在寻找其他线程来获取该事件,您可以使用BlockingQueue。然后你的另一个线程可以执行queue.take(),这将等待有事件要处理。但我不确定这里的目标是什么。

非常奇怪的一件事是使用ExecutorService的地图。你真的需要多个吗?我怀疑你真的应该使用一个Executors.newCachedThreadPool()。但是,您可能希望单个线程处理具有相同ID的所有请求,在这种情况下您的代码应该可以工作。当你想要关闭你的应用程序时,我假设你正在做类似的事情:

for (ExecutorService executor : executors.values()) {
    executor.shutdown();
}