0

我有一个应用程序可以创建数百个对象 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);
        }
    }
}

}

4

2 回答 2

2

我不喜欢通过使用 foo_inst.b_queue.remove 将 B 类和 C 类绑定到 Foo。这使得架构耦合过于紧密。尽量通过接口和其他抽象机制来避免这种情况。

您已经确定了一个可能的并发问题。一些锁定,使用前检查或其他机制,以避免双重删除。也许

if ( foo_inst.b_queue.contains(this)  )
{
  foo_inst.b_queue.remove(this);
}
于 2011-07-31T10:18:07.310 回答
1

为什么不直接使用HashSets - 这样,您可以将 B 和 C 实例存储在 2 个单独的哈希集中。实际上,您甚至可以通过声明为 B 和 C 对象使用 1 个哈希集HashSet<Object> bnc = HashSet<Object>()。现在,如果要删除特定实例,只需使用 remove(Object o) 方法。如果您想同时执行此操作,最简单的方法是同步对您各自的哈希集或哈希集的访问。

编辑:

嗯,所以我只是查看了您的解决方案,这里是您如何使用 HashSets 以线程安全的方式执行此操作。

public class Foo implements Foo_interface{    
    HashSet<Object> bnc = new HashSet<Object>();
    //thread safety using monitors
    public synchronized insert(Object o) {
        bnc.add(o);
    }
    public synchronized delete(Object o) {
        bnc.remove(o);
    }
}

private class B implements Runnable{

    Foo f;

    public B(Foo f) {
        this.f = f;
        this.f.insert(this);
    }

    public void run(){
        try{
            //some code
        }catch(Exception e{
            this.f.delete(this);
        }
    }
}

private class C implements Runnable{

    Foo f;

    public C(Foo f) {
        this.f = f;
        this.f.insert(this);
    }

    public void run(){
        try{
            //some code
        }catch(Exception e{
            this.f.delete(this);
        }
    }
}

如果您真的想使用键(在这种情况下实际上是不必要的),您始终可以以类似的方式实现 HashMap 而不是 HashSet。只需记住将密钥传递给相应的构造函数。

于 2011-07-31T10:41:39.350 回答