Domanda

Così sto pensando di costruire un progetto hobby, una tantum genere di cose, giusto per rispolverare la mia programmazione / progettazione.

E 'fondamentalmente un multi threaded ragnatela, aggiornando la stessa struttura dati object-> int.

Quindi è sicuramente eccessivo di utilizzare un database per questo, e l'unica cosa che riuscivo a pensare è un Singleton thread-safe utilizzato per contenere la mia struttura dati. http : //web.archive.org/web/20121106190537/http: //www.ibm.com/developerworks/java/library/j-dcl/index.html

C'è un approccio diverso dovrei guardare per?

È stato utile?

Soluzione

interblocco ricontrollato ha dimostrato di essere corretto e imperfetta (come almeno in Java). Fare una ricerca o guardare di Wikipedia per il motivo esatto.

In primo luogo è la correttezza del programma. Se il codice non è thread-safe (in un ambiente multi-threaded) allora è rotto. Correttezza viene prima l'ottimizzazione delle prestazioni.

Per essere corretta dovrete sincronizzare l'intero metodo getInstance

public static synchronized Singleton getInstance() {
   if (instance==null) ...
}

o staticamente inizializzarlo

private static final Singleton INSTANCE = new Singleton();

Altri suggerimenti

Utilizzando l'inizializzazione pigra per il database in un web crawler non è probabilmente vale la pena. inizializzazione differita aggiunge complessità e un colpo di velocità in corso. Un caso in cui sia giustificato è quando c'è una buona probabilità non saranno mai necessari i dati. Inoltre, in un'applicazione interattiva, può essere utilizzato per ridurre il tempo di avvio e dare il illusione di velocità.

Per un'applicazione non interattiva come un web-crawler, che sarà sicuramente bisogno il suo database di esistere subito, l'inizializzazione pigra è una scelta povera.

D'altra parte, un web crawler è facilmente parallelizzabile, e beneficerà notevolmente da essere multi-thread. Usandolo come un esercizio di padroneggiare la libreria java.util.concurrent sarebbe estremamente utile. In particolare, guarda ConcurrentHashMap e < a href = "http://java.sun.com/javase/6/docs/api/java/util/concurrent/ConcurrentSkipListMap.html" rel = "noreferrer"> ConcurrentSkipListMap, che consentirà a più thread leggere e aggiornare una mappa condivisa.

Quando si sbarazzarsi di inizializzazione differita, il più semplice pattern Singleton è qualcosa di simile:

class Singleton {

  static final Singleton INSTANCE = new Singleton();

  private Singleton() { }

  ...

}

Il final parola chiave è la chiave qui. Anche se si fornisce un static "getter" per il singleton piuttosto che permettere l'accesso campo diretto, rendendo il final Singleton aiuta a garantire la correttezza e consente di ottimizzare più aggressiva dal compilatore JIT.

Se la vostra vita dipendesse da pochi microsecondi, allora vi consiglio di ottimizzare la risorsa di blocco a dove realmente importava.

Ma in questo caso la parola chiave qui è progetto hobby !

Il che significa che se si è sincronizzato l'intero getInstance () metodo che andrà bene nel 99,9% dei casi. Non voglio raccomandare di farlo in altro modo.

In seguito, se si prova per mezzo di profiling che il getInstance () La sincronizzazione è il collo di bottiglia del vostro progetto, allora si può andare avanti e ottimizzare la concorrenza. Ma ho davvero dubbi che causerà problemi.

Jeach!

Prova il Bill Pugh soluzione di inizializzazione sul supporto richiesta idioma. La soluzione è la più portabile su diversi compilatori Java e le macchine virtuali. La soluzione è thread-safe senza richiedere speciali costrutti di linguaggio (cioè volatile e / o sincronizzato).

http://en.wikipedia.org/wiki/Singleton_pattern#The_solution_of_Bill_Pugh

come Joshua Bloch sostiene nel suo libro "Effective Java 2 ° edizione" Ho anche d'accordo che un unico tipo di elemento enum è il modo migliore per attuare un Singleton.

public enum Singleton {
  INSTANCE;

  public void doSomething() { ... }
}

Se si guarda al fondo di questo articolo, vedrete il suggerimento di utilizzare solo un campo statico. Questa sarebbe la mia inclinazione: non ha realmente bisogno di un'istanza pigro (quindi non c'è bisogno getInstance() essere sia una funzione di accesso e un metodo di fabbrica). Si vuole solo assicurarsi di avere una e una sola di queste cose. Se si ha realmente bisogno l'accesso globale a una cosa del genere, mi piacerebbe utilizzare che il codice di esempio verso il fondo :

class Singleton
{
  private Vector v;
  private boolean inUse;
  private static Singleton instance = new Singleton();

  private Singleton()
  {
    v = new Vector();
    inUse = true;
    //...
  }

  public static Singleton getInstance()
  {
    return instance;
  }
}

Si noti che il Singleton è ora costruito durante l'installazione di campi statici. Questo dovrebbe funzionare e non affrontare i rischi di threading di potenzialmente cose mis-sincronizzazione.

Detto questo, forse quello che si ha realmente bisogno è una delle strutture di dati thread-safe disponibili nelle JDK moderni. Per esempio, io sono un grande fan della ConcurrentHashMap : (! FTW). filo di sicurezza più io non è necessario scrivere il codice

Perché non creare una struttura di dati che si passa ad ognuno dei fili come iniezione di dipendenza. In questo modo non è necessario un Singleton. Hai ancora bisogno di fare il thread-safe.

L'articolo si fa riferimento parla solo di rendere la creazione dell'oggetto Singleton, presumibilmente una collezione, in questo caso, thread-safe. È inoltre necessario una raccolta thread-safe in modo che le operazioni di raccolta anche lavorare come previsto. Assicurarsi che la raccolta degli elementi del Singleton è sincronizzato, magari utilizzando un ConcurrentHashMap .

Leggi questo articolo Attuazione del pattern Singleton in C #

public sealed class Singleton
{
    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

Come su:

public static Singleton getInstance() {
  if (instance == null) {
    synchronize(Singleton.class) {
      if (instance == null) {
         instance = new Singleton();
      }
    }
  }

  return instance;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top