我有一个类管理器,它将同时由多个线程访问,我想知道我是否以正确的方式进行了操作?
另外我认为我需要RemoveFoo是原子的,但我不确定
public class Manager
{
private ConcurrentHashMap<String, Foo> foos;
//init in constructor
public RemoveFoo(String name)
{
Foo foo = foos.Get(name);
foo.RemoveAll();
foos.Remove(name);
}
public AddFoo(Foo foo)
{...}
}
public class Foo
{
private Map<String,Bar> bars;
//intialize it in constructor
//same for RemoveBar
public void AddBar(Bar bar)
{
synchronized(this)
{
bars.put(bar.id, bar);
}
}
public void RemoveAll()
{
synchronized(this)
{
//some before removall logic for each one
bars.remove(bar.id, bar);
}
}
}
public class Bar
{}
答案 0 :(得分:4)
您使用ConcurrentHashMap时不需要同步方法,但请注意Foo foo = foos.Get(name)
可能会返回null,因为另一个线程可能已经从地图中删除了该条目。
成员可以声明为Map<String, Foo> foos
,但必须初始为foos = new ConcurrentHashMap<String, Foo>;
答案 1 :(得分:3)
RemoveFoo
可能会有问题。我建议使用:
Foo foo = foos.remove (name);
if (foo != null) foo.removeAll();
代替。这可确保地图在get()
和remove()
之间不会发生变化。
在Foo
中,只需在bars
上进行同步,而不是整个实例。但这只是一个小小的优化。
答案 2 :(得分:1)
将RemoveFoo(String)
声明为synchronized
:
public synchronized void RemoveFoo(String name) {
…
}
另外,请注意以下事项:
removeFoo
代替RemoveFoo
。这不是C#。 :)public removeFoo()
不是有效的方法声明,它必须是public void removeFoo()
。答案 3 :(得分:1)
如果你在Foo中使用concurrentHashMap
private Map<String,Bar> bars = new ConcurrentHashMap<String, Bar>();
也许你可以在Foo中取消同步。
答案 4 :(得分:1)
我不确定你要对Foo和Bar做什么,但它看起来像是一种解除分配的模式。
如果他们没有引用他们,只需调用foos.Remove(name);并让GC引擎处理释放。