Question

Je pense à la construction d'un projet passe-temps, un hors genre de chose, juste pour rafraîchir ma programmation / conception.

Il est essentiellement une araignée web multifil, mettre à jour la même structure de données object-> int.

Il est certainement exagéré d'utiliser une base de données pour cela, et la seule chose que je pouvais penser est un singleton thread-safe utilisé pour contenir ma structure de données. http : //web.archive.org/web/20121106190537/http: //www.ibm.com/developerworks/java/library/j-dcl/index.html

Y at-il une autre approche que je devrais regarder dans?

Était-ce utile?

La solution

Verrouillage revérifié a été avéré incorrect et erroné (comme moins en Java). Faites une recherche ou regarder entrée de Wikipedia pour la raison exacte.

D'abord et avant tout la correction du programme. Si votre code n'est pas thread-safe (dans un environnement multi-thread), il est cassé. Vient avant de justesse l'optimisation des performances.

Pour être correct, vous devrez synchroniser l'ensemble de la méthode getInstance

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

ou initialiser statiquement il

private static final Singleton INSTANCE = new Singleton();

Autres conseils

En utilisant l'initialisation paresseuse pour la base de données dans un robot web est sans doute pas la peine. initialisation Lazy ajoute à la complexité et un coup de vitesse en cours. Un cas où il est justifié est quand il y a une bonne chance les données ne seront jamais nécessaires. En outre, dans une application interactive, il peut être utilisé pour réduire le temps de démarrage et de donner la illusion de la vitesse.

Pour une application non interactive comme un web crawler, qui devra sûrement sa base de données existe tout de suite, l'initialisation paresseuse est un mauvais ajustement.

D'autre part, un robot web est facilement parallélisables, et bénéficiera grandement d'être multi-thread. L'utiliser comme un exercice pour maîtriser la bibliothèque java.util.concurrent serait extrêmement utile. Plus précisément, regardez ConcurrentHashMap et < a href = "http://java.sun.com/javase/6/docs/api/java/util/concurrent/ConcurrentSkipListMap.html" rel = "noreferrer"> ConcurrentSkipListMap, qui va permettre à plusieurs threads lire et mettre à jour une carte partagée.

Lorsque vous vous débarrasser de l'initialisation paresseuse, le modèle Singleton est quelque chose comme simple ceci:

class Singleton {

  static final Singleton INSTANCE = new Singleton();

  private Singleton() { }

  ...

}

Le final mot-clé est la clé ici. Même si vous fournissez un static « getter » pour le singleton plutôt que de permettre un accès direct sur le terrain, ce qui rend le final singleton aide à assurer l'exactitude et permet une optimisation plus agressive par le compilateur JIT.

Si votre vie dépendait de quelques microsecondes alors je vous conseille d'optimiser votre verrouillage des ressources là où il importait effectivement.

Mais dans ce cas, le mot clé est ici projet passe-temps !

Ce qui signifie que si vous avez synchronisé l'ensemble getInstance () méthode sera bien dans 99,9% des cas. Je ne recommanderais pas le faire autrement.

Plus tard, si vous prouvez au moyen de profilage que le getInstance () synchronisation est le goulot d'étranglement de votre projet, vous pouvez passer et optimiser la concurrence. Mais je doute vraiment vous causera des problèmes.

Jeach!

Essayez le Bill Pugh solution de support d'initialisation à la demande. La solution est le plus portable entre les différents compilateurs Java et des machines virtuelles. La solution est thread-safe sans nécessiter des éléments de langage particuliers (à savoir volatile et / ou synchronisé).

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

comme Joshua Bloch affirme dans son livre « 2ème édition java efficace » Je suis d'accord aussi qu'un seul élément de type ENUM est la meilleure façon de mettre en œuvre un singleton.

public enum Singleton {
  INSTANCE;

  public void doSomething() { ... }
}

Si vous regardez en bas de cet article, vous verrez la suggestion d'utiliser simplement un champ statique. Ce serait mon inclination: vous n'avez pas vraiment besoin instanciation paresseux (vous n'avez pas besoin getInstance() être à la fois un accesseur et une méthode de fabrication). Vous voulez juste vous assurer que vous avez une et une seule de ces choses. Si vous avez vraiment besoin d'un accès global à une telle chose, j'utiliser cet échantillon de code vers le bas très:

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;
  }
}

Notez que le Singleton est maintenant construit lors de l'installation de champs statiques. Cela devrait fonctionner et non face aux risques de filetage des choses potentiellement mal synchronisation.

Cela dit, peut-être ce que vous avez vraiment besoin est l'une des structures de données thread-safe disponibles dans les JDKs modernes. Par exemple, je suis un grand fan de la ConcurrentHashMap : (! FTW). fil de sécurité plus je ne pas écrire le code

Pourquoi ne pas créer une structure de données que vous passez à chacun des fils que l'injection de dépendance. De cette façon, vous n'avez pas besoin d'un singleton. Vous devez toujours faire le fil en toute sécurité.

L'article que vous avez mentionné ne parle que de faire de la création de l'objet singleton, vraisemblablement une collection dans ce cas, thread-safe. Vous devez également une collection thread-safe pour que les opérations de collecte fonctionnent également comme prévu. Assurez-vous que la collection sous-jacente dans le singleton est synchronisé, en utilisant peut-être un ConcurrentHashMap .

Consultez cet article mise en œuvre du modèle Singleton en 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();
    }
}

Que diriez-vous:

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

  return instance;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top