【发布时间】:2016-09-19 10:40:32
【问题描述】:
我持有一个对象地图,每次将一个对象添加到其中时,都需要通知地图中的所有其他对象新对象,反之亦然。这些对象在它们自己的 thread 进程上运行(每个都从main 开始)可以调用将它们添加到映射的方法,因此可以在迭代期间添加对象对象。
这是我的一些示例代码。这是我在上面谈论的对象
class Notifier {
String name;
Hub hub;
Notifier(String name) {
this.name = name;
hub.add(this);
}
void acknowledge(String name) {
System.out.println(this.name + " was notified of " + name);
}
}
这是拿着地图的东西
public class Hub {
ConcurrentMap<String, Notifier> map = new ConcurrentHashMap<>();
void add(Notifier notifier) {
map.putIfAbsent(notifier.name, notifier);
Iterator<Entry<String, Notifier>> it = map.entrySet().iterator();
while (it.hasNext()) {
Entry<String, Notifier> entry = it.next();
if (!entry.getKey().equals(notifier.name)) {
entry.getValue().acknowledge(notifier.name);
notifier.acknowledge(entry.getKey());
}
}
}
}
我试过ConcurrentHashMap,但不一定是这样。我的问题是我得到的结果是,如果我一起启动它们的线程,每个对象都会多次收到关于另一个对象的通知。我明白了
notifier1 被通知了 notifier2
notifier1 被通知了 notifier2
notifier1 被通知了 notifier3
notifier1 被通知了 notifier3
notifier1 被通知了 notifier4
notifier1 被通知了 notifier4
其他的也一样。如果我一个接一个地启动它们,那么我让每个完成添加我得到正确的结果
notifier1 被通知了 notifier2
notifier1 被通知了 notifier3
notifier1 被通知了 notifier4
其他类似。
我知道我选择的这张地图不能保证在添加(放置)值时更新迭代器,所以我认为这就是它发生的原因。无论如何,我知道上述实验中存在一些线程竞争。
我怎样才能让每个对象都被准确地通知所有其他对象的 1 次?也许这个并发地图不好,我需要同步一些东西?我不在乎添加的顺序。
【问题讨论】:
-
这些是什么类型的对象?是否有充分的理由让它们成为独立线程而不是使用回调方法?
-
@chrylis 它就像客户端和服务器。每个进来的客户都会收到所有其他客户的通知,他们也会收到通知。这不是一种回调,因为集线器调用了通知对象上的方法吗?对不起,如果我不明白。
-
有点,但您特别说它们“在自己的线程上运行”,这与您在此处发布的代码不匹配。
-
@chrylis 每个都是通过
main单独启动的,所以它们是不同的应用程序。我认为这也意味着它们在不同的线程上。 -
哦,那么它们是完全独立的进程,这使得这是一个完全不同的问题。嗯。
标签: java concurrency synchronization iteration concurrenthashmap