quel est le meilleur modèle ou de la méthode de la charge statique de cache?
Disons que j'ai les suivantes (à supposer limitée à java 1.4 donc pas de génériques) :
public class CacheManager {
static HashMap states;
static boolean statesLoaded;
public static String getState(String abbrev) {
if(!statesLoaded) {
loadStates();
}
return (String) states.get(abbrev);
}
private static void loadStates() {
//JDBC stuff to load the data
statesLoaded = true;
}
}
Dans une haute résistance multi-thread de l'environnement comme une application web serveur, ce qui pourrait théoriquement avoir des problèmes si > 1 thread tente d'obtenir et de charger le cache en même temps. (Plus loin en supposant que il n'y a pas de code de démarrage sur la web app pour initialiser le cache)
Est tout simplement à l'aide de Collections.synchronizedMap suffisante pour résoudre ce problème? Le retourné synchronizedMap ont des problèmes de performances lorsque vous faites get(), si beaucoup de threads accèdent?
Ou serait-il mieux d'avoir un non-synchronisé table de hachage, et, au lieu de se synchroniser sur la méthode de chargement ou variable booléenne? Je pense que si vous avez synchronisé à l'un de ces, vous pourriez finir vers le haut de verrouillage de la classe.
Par exemple, si la méthode de chargement, a été synchronisé, si 2 fils entrez le getStates() en même temps, et de voir que statesLoaded est faux. Le premier obtient un verrou sur la méthode, charge le cache et jeux de statesLoaded de vrai. Malheureusement, le 2ème fil a déjà évalué que statesLoaded était faux, et procède à la méthode de chargement, une fois que le verrou est libre. N'est-ce pas aller de l'avant et de charger le cache de nouveau?
OriginalL'auteur user26270 | 2009-07-17
Vous devez vous connecter pour publier un commentaire.
La meilleure façon de charger le cache dans ce cas est de prendre avantage de la JVM initialisation statique:
Le cache va être chargé pour la première fois la classe est utilisée, et que depuis l'initialisation statique est thread-safe, la carte sera remplie en toute sécurité. Tous les appels suivants de récupérer les valeurs peuvent être effectuées sans aucun verrouillage impliqués.
C'est toujours une bonne idée de profiter d'initialisation statique à chaque fois que possible. Il est sûr, efficace, et souvent assez simple.
OriginalL'auteur sjlee
Vous devez synchroniser cette case:
Pourquoi ? Plusieurs threads peuvent
get()
sur la carte sans aucun problème. Cependant, vous devez atomiquement vérifier lastatesLoaded
drapeau, la charge de l'état, et de définir l'indicateur, le vérifier. Sinon, vous pourriez vous (dire) la charge des etats, mais le drapeau serait encore de ne pas être ensemble et d'être visible en tant que telle à partir d'un autre thread.(Vous pourriez potentiellement laisser ce non synchronisés et de permettre la possibilité de plusieurs threads pour ré-initialiser le cache, mais au moins ce n'est pas une bonne programmation de pratiquer, et, au pire, pourrait vous causer des problèmes par la suite avec de grandes caches, les différentes implémentations etc.)
Par conséquent, avoir une synchronisée carte n'est pas assez (ce qui est tout à fait à tort, d'ailleurs).
Je ne voudrais pas vous soucier de l'impact sur les performances de la synchronisation. Il sert à être un problème dans le passé, mais il est beaucoup plus légère d'exploitation. Comme toujours, de mesurer et d'optimiser quand il le faut. Prématuré d'optimisation est souvent un gaspillage d'efforts.
De sorte que vous pouvez verrouiller sur l'objet contenant, qui est assez grossier, ou vous pouvez fournir un simple objet : Objet de verrouillage = new Object(); ce qui serait la serrure pour cette méthode et rien d'autre.
N'oubliez pas que vous n'êtes pas de blocage autour de la get();
OriginalL'auteur Brian Agnew
N'essayez pas de les faire vous-même. Utiliser un conteneur IoC comme le Printemps ou Guide et vous le cadre de gestion et initialiser le singleton pour vous. Cela rend vos problèmes de synchronisation beaucoup plus gérable.
OriginalL'auteur skaffman
quoi de mal avec le pattern Singleton?
OriginalL'auteur Trevor Harrison
Depuis statesLoaded seulement peut aller de faux à vrai, j'irais pour une solution où vous vérifiez d'abord la statesLoaded est vrai, si c'est vous, sautez simplement la initalization logique. Si elle n'est pas à vous de le verrouiller et de vérifier à nouveau et si c'est encore faux vous chargez les etats du pays et de définir l'indicateur de vrai.
Cela signifie que n'importe quel thread appelant getState une fois que le cache est initialisé sera "début" et de l'utilisation de la carte sans verrouillage.
quelque chose comme:
Cela signifie que le verrouillage ne participeront avant et pendant les initalization arrive.
Si ce serait C, je voudrais aussi assurez-vous de faire le
statesLoaded
variable
d'être volatile assurez-vous que le compilateur d'optimiser la deuxième case. Je ne sais pas comment java se comporte quand il s'agit de situations comme ça, mais je suppose qu'il considère que toutes les données partagées comme statesLoaded être potentiellement sale quand nous allons dans les étendues de synchronisation.OriginalL'auteur Laserallan
+1 pour le conteneur IoC. Utiliser Le Printemps. Créer CacheManager classe non statique et définir CacheManaget au Printemps contexte config.
1 Non-statique CacheManager version
2 Définir haricot de CacheManager au printemps contexte ou de l'utilisation @Service/@Composant d'annotation (ne pas foget définir le chemin de balayage pour les annotations)
3 Injecter votre cache bean ce que vous voulez avec le Printemps config ou @Autowire annotation
au-dessus de code écrit n'est pas thread-safe , réf:cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
OriginalL'auteur alexey28