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 でキューに入れられます。これは、それらがワークキューに 2 回存在する可能性があり、同時に 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

HashSetを使用してみませんか?このようにして、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);
        }
    }
}

本当にキーを使用したい場合(この場合は実際には不要です)、同様の方法でHashSetの代わりにHashMapをいつでも実装できます。キーをそれぞれのコンストラクターに渡すことを忘れないでください。

于 2011-07-31T10:41:39.350 に答える