2011-07-31 13 views
0

Iオブジェクトfooが有する2つのキュー(b_queueとc_queue)、タイプBのオブジェクトで満たされた一方及び他方を含むオブジェクトの階層があり、いくつかのオブジェクトBおよびCJava:キューからオブジェクトを同時に削除する。

のインスタンスの数百を作成するアプリケーションを持っています

BまたはCで何らかのイベントが発生した場合、オブジェクトFooのキューから自分自身を削除する必要があります。

私の解決策は、オブジェクトBまたはCの構築時に、Fooのインスタンス(foo_instと呼ぶ)を渡してキューに格納します。 次にBまたはCの中で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); 
     } 
    } 
} 

}

+0

Java Concurrency Useというタイトルである必要があります。メモリの問題はどこで発生していますか? –

答えて

1

- このように、あなたは2つの別々のhashsetsにBとCのインスタンスを格納することができます。実際には、HashSet<Object> bnc = HashSet<Object>()と宣言することで、BオブジェクトとCオブジェクトの両方に1つのハッシュセットを使用することもできます。特定のインスタンスを削除する場合は、remove(Object o)メソッドを使用します。これを同時に実行したい場合は、最も簡単なのは、それぞれのハッシュセットまたはハッシュセットへのアクセスを同期させることです。

EDIT:

ええと、私はちょうどあなたのソリューションを見て、ここにあなたが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を実装することができます。それぞれのコンストラクタにキーを渡すことを忘れないでください。

2

は、私はクラスBとCの抱き合わせが好きではありませんfoo_inst.b_queue.removeを使用してFooに渡します。これにより、アーキテクチャが緊密に結合されます。インタフェースやその他の抽象化メカニズムによってこれを避けるようにしてください。

可能なコヒーレンシーの問題を特定しました。いくつかのロック、使用前にチェックするか、ダブル除去を避けるための他のメカニズム。あなただけHashSetsを使用していないのはなぜおそらく

if (foo_inst.b_queue.contains(this) ) 
{ 
    foo_inst.b_queue.remove(this); 
} 
+0

アーキテクチャをあまりにも強く結合させることによって、あなたが意味するものを理解できますが、抽象化メカニズムを使用してこれをどのように解決できますか?私はこのいたずらにしっかりと結合された方法を避けたいと思っているので、何日間かの方法を考えようとしてきましたが、どう考えていないのですか。 – Vort3x

+0

私はキュー構造の代わりにConcurrencyHashMapを使用することを考えていました。これは、BとCの内部でオブジェクトBとCに使用されているKeyオブジェクトを格納するように強制します。これはもう一度、かなり面倒です。 :( – Vort3x

+0

Booqueueからbを削除するpublic void remove(B b)のようなメソッドをFooで作成すると、BはFooの内部構造を知る必要はありません。これはほんの始まりです。 –

関連する問題