2014-06-12 4 views
0

J'essayais d'écrire une classe singleton, qui sera utilisée pour la mise en œuvre simple du cache. J'ai suivi un modèle de verrouillage double-coché pour obtenir l'instance où l'instance est un membre volatile dans la classe. Il contient également un HashTable pour le stockage des données.Concurrence variable dans le modèle Singleton Class

Si j'essaie d'accéder à une valeur dans la carte via une méthode, devrais-je fournir un mot-clé 'synchronized' pour bloquer l'accès simultané? Je pose cette question parce que le UserCache lui-même est en utilisant le double synchronisée-verrouillage vérifiée dans la méthode getInstance()

Ou est-il préférable d'utiliser un ConcurrentHashMap au lieu de Hashtable?

Voir l'extrait de code ci-dessous pour plus de détails.

public class UserCache { 

private volatile static UserCache instance; 
private Hashtable<String, User> users = null; 

private UserCache() { 
    this.users = new Hashtable<String, User>(); 
} 

public static UserCache getInstance() { 
    if (instance == null) { 
     synchronized (UserCache.class) { 
      if (instance == null) { 
       instance = new UserCache(); 
      } 
     } 
    } 
    return instance; 
} 

public synchronized User getUser(String userUid) { 
    return this.users.get(userUid); 
} 

public synchronized boolean addUser(User user) { 

    if (isValidUser(user.getUserUid())) { 

     return false; 
    } 
    this.users.put(user.getUserUid(), user); 

    return true; 
} 

... 

Tout conseil serait grandement apprécié :)

Merci à l'avance

+0

mieux utiliser une carte de hachage simultanée, car synchronisé ne vous aidera pas beaucoup. –

+0

Merci pour votre suggestion @RomanC – dasrohith

Répondre

0

Si tel est l'étendue de votre classe, puis un ConcurrentHashMap fonctionnerait. Si vous avez d'autres méthodes où plus d'un simple get/put sur la carte doit être synchronisé, une ReadWriteLock est une bonne option pour autoriser les lectures simultanées.

Une autre alternative à votre revérifié verrouillage avec une statique volatile serait d'utiliser une classe interne:

private static final class DeferredLoader { 
    static final UserCache INSTANCE = new UserCache(); 
} 

public static UserCache getInstance() { 
    return DeferredLoader.INSTANCE; 
} 

Cela a l'avantage d'être immuable et reporte encore la création de l'instance jusqu'à ce que la méthode getInstance est appelé la première fois.

+0

merci pour votre suggestion @Brett Okken. Je vais utiliser une hashmap simultanée – dasrohith

0

Si vos méthodes sont synchronisées, je ne vois pas le besoin de ConcurrentHashMap. Pourtant, je voudrais utiliser la carte <,> au lieu de Hashtable. C'est une bonne pratique de favoriser les interfaces.