Domanda

ho una classe Manager che sta per essere accessibile da più thread allo stesso tempo, voglio sapere se ho fatto nel modo giusto?
anche Penso di aver bisogno di essere RemoveFoo atomica, ma non sono sicuro

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
{}
È stato utile?

Soluzione

RemoveFoo potrebbe essere problematico. Suggerisco di usare:

Foo foo = foos.remove (name);
if (foo != null) foo.removeAll();

, invece. Questo fa in modo che la mappa non cambia tra get() e remove().

In Foo, è sufficiente per sincronizzare il bars anziché l'intera istanza. Ma questa è solo un'ottimizzazione minore.

Altri suggerimenti

Non hai bisogno di metodi sincronizzati come si utilizza un ConcurrentHashMap, però essere consapevoli che Foo foo = foos.Get(name) potrebbe tornare null come un altro thread potrebbe già aver rimosso la voce dalla mappa.

I membri possono essere dichiarati come Map<String, Foo> foos, ma devono essere initialsed come foos = new ConcurrentHashMap<String, Foo>;

Dichiarare RemoveFoo(String) come synchronized:

public synchronized void RemoveFoo(String name) {
    …
}

Inoltre, essere informati di quanto segue:

  • nomi dei metodi dovrebbero essere minuscole, ad esempio, removeFoo invece di RemoveFoo. Questo non è C #. :)
  • Ogni metodo ha bisogno di un tipo di ritorno: public removeFoo() non è una dichiarazione di metodo validi, ha bisogno di essere public void removeFoo()
  • .

Se si utilizza un ConcurrentHashMap in Foo come

private Map<String,Bar> bars = new ConcurrentHashMap<String, Bar>();

forse si può fare a meno la sincronizzazione in Foo pure.

Non sono sicuro di che cosa avete intenzione di fare sul Foo e bar, ma sembra che un modello di deallocazione.

Se non si fa riferimento da altri, basta chiamare foos.Remove (nome); e lasciare che il motore GC gestire la deallocazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top