Java:同时从队列中删除对象。
我有一个应用程序,它创建了一些对象 B 和 C 的数百个实例。
对象 Foo 包含 2 个队列(b_queue 和 c_queue),一个队列填充 B 类型的对象,另一个填充 C 类型的对象。
有一个对象层次结构,其中 B 或 C 中发生某些事件,我希望它们将自己从对象 Foo 的队列中删除。
我的解决方案是构造一个对象 B 或 C,将 Foo 的实例(称为 foo_inst)交给它们,该实例将把它们存储在队列中。 然后在B或CI内部就可以调用foo_inst.b_queue.remove(this)。
1)这是一个好的/有效的方法吗?或者应该避免这种情况?
B 和 C 都是 Runnable 对象,并且将使用 ThreadPoolExecutor 排队。这意味着它们可能会在工作队列中出现两次,并且可能会尝试同时调用 foo_inst.b_queue.remove(this) ,或者在调用完成之后调用。
2)这也会带来问题吗?
非常感谢任何帮助或提示。
好的,到目前为止,我已经在一些帮助下成功做到了这一点。(欢迎更多帮助):
public class Foo implements Foo_interface{
ConcurrentHashMap<Key,B> b_map = new ConcurrentHashMap<Key,B>();
ConcurrentHashMap<Key,C> c_map = new ConcurrentHashMap<Key,C>();
public void removeB(Key k){
b_map.remove(k);
}
public void removeC(Key k){
c_map.remove(k);
}
private class B implements Runnable{
Foo foo_inst;
Key key;
public B(Foo foo,Key key){
this.foo=foo;
this.key=key;
}
public void run(){
try{
//some code
}catch(Exception e{
foo.removeB(key);
}
}
}
private class C implements Runnable{
Foo foo_inst;
Key key;
public C(Foo foo,Key key){
this.foo=foo;
this.key = key;
}
public void run(){
try{
//some code
}catch(Exception e{
foo.removeC(key);
}
}
}
}
I have an application that creates hundreds of instances of some objects B and C.
There is an object hierarchy where object Foo contains 2 queues (b_queue and c_queue), one filled with objects of type B and the other with objects of type C.
When some event occurs in B or C, I want them to remove themselves from the queue in object Foo.
My solution is on construction of an object B or C, to hand them the instance of Foo (call it foo_inst) that will be storing them in its queues.
Then inside B or C I can just call foo_inst.b_queue.remove(this).
1) Will this be a good/efficient way to do so, or should this be avoided?
Both B and C are Runnable objects, and will be queued with a ThreadPoolExecutor. This means that they may be on the workqueue twice, and might try to call foo_inst.b_queue.remove(this) concurrently, or after it has already been done.
2) Will this pose a problem as well?
Any help or tips much appreciated.
Okay so far I've managed to get this far with some help.(any more help welcome):
public class Foo implements Foo_interface{
ConcurrentHashMap<Key,B> b_map = new ConcurrentHashMap<Key,B>();
ConcurrentHashMap<Key,C> c_map = new ConcurrentHashMap<Key,C>();
public void removeB(Key k){
b_map.remove(k);
}
public void removeC(Key k){
c_map.remove(k);
}
private class B implements Runnable{
Foo foo_inst;
Key key;
public B(Foo foo,Key key){
this.foo=foo;
this.key=key;
}
public void run(){
try{
//some code
}catch(Exception e{
foo.removeB(key);
}
}
}
private class C implements Runnable{
Foo foo_inst;
Key key;
public C(Foo foo,Key key){
this.foo=foo;
this.key = key;
}
public void run(){
try{
//some code
}catch(Exception e{
foo.removeC(key);
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不喜欢通过使用 foo_inst.b_queue.remove 将类 B 和 C 绑定到 Foo。这使得架构耦合过于紧密。尝试通过接口和其他抽象机制来避免这种情况。
您已发现可能存在并发问题。一些锁定、使用前检查或其他机制以避免双重移除。也许
I don't like the tying of classes B and C to Foo by the uses of foo_inst.b_queue.remove. This makes the architecture too tightly coupled. Try to avoid this by interfaces and other abstraction mechanisms.
You have identified a possible cocurrency issue. Some locking, check before use or other mechanism to avoid the double remove. Perhaps
为什么不直接使用 HashSets- 这样,您可以将 B 和 C 实例存储在 2 个单独的哈希集中。实际上,您甚至可以通过声明
HashSet
编辑:
呃,所以我刚刚查看了您的解决方案,以下是如何使用 HashSets 以线程安全的方式执行此操作。
如果你确实想使用键(在这种情况下实际上是不必要的),你总是可以以类似的方式实现 HashMap 而不是 HashSet。只需记住将密钥传递给相应的构造函数即可。
Why don't you just use HashSets- this way, you can store B and C instances in 2 separate hashsets. Actually, you can even use 1 hashset for both B and C objects by declaring
HashSet<Object> bnc = HashSet<Object>()
. Now if you want to remove a specific instance, just use the remove(Object o) method. If you want to do this concurrently, the simplest thing would be to synchronize access to your respective hashsets or hashset.EDIT:
Uh, so I just looked at your solution and here is how you could do this in a thread-safe manner with HashSets.
If you really want to use keys (which is actually unnecessary in this case), you can always implement a HashMap instead of a HashSet in a similar fashion. Just remember to pass the key to the respective constructors.