Les meilleures pratiques pour la mise à jour/écriture de variable statique?
J'ai un projet qui affiche de documentation du département. Je stocke toutes les docs (obtenir à partir de la base de données) dans un arrayList statique. Toutes les X heures, j'ai les arrayList reconstruit basé sur le nouveau doc (le cas échéant) à partir de la base de données. Il y a aussi une variable statique de contrôle pour reconstruire ce tableau ou non, de fixer et d'annuler en une méthode qui ne la reconstruction de la tâche. Chaque navigateur web frappé le serveur va créer cette classe de l'instance, mais le doc arrayList et que la variable de contrôle est partagé entre toutes les instances de classe.
Trouver des Bogues outil se plaint que "Écrire à champ statique someArrayName et someVariableName à partir de la méthode d'instance someClassMethod". Semble que ce n'est pas la bonne chose à faire (laisser instance de la classe de la méthode d'écriture de champ statique). Quelqu'un a de bons conseils sur la façon de contourner ce problème ? Merci.
Genre oui. Depuis chaque coup (une nouvelle session ou de la nouvelle vue si JSF2.0) va générer une instance de classe, je ne veux pas créer de nombreux de nombreux dupliqué arrayList contient les mêmes docs. Merci.
Charles: vous voulez un singleton "gestionnaire" de l'objet que les instances peuvent se référer. À l'aide d'une instance statique pour mettre en œuvre le singleton a quelques passages délicats effets secondaires. La meilleure façon est de créer un gestionnaire unique de l'objet, et le point chacun de vos instances pour que d'une certaine façon. Si vous travaillez dans un cadre qui crée votre cas (vs vous en cours d'exécution java vous-même), de rechercher comment créer des objets singleton. Tomcat, par exemple, a un certain type de contexte que vous pouvez lire/écrire, comme une façon de traiter avec la persistance d'un état, mais je ne suis pas familier avec elle.
Merci pour l'aide. J'ai ajouté une classe singleton, là, de reconstruire la documentation statique de l'arbre ou static arraylist toutes les X heures. Depuis que je suis en utilisant JSF JSF PhaseListeners sont partagés par tous les JSF web demandes, alors, j'ai mis de l'instanciation de classe singleton dans une phaseListener, a bien fonctionné. Bien que, il y a un thread d'accès risque de tout arbre en cours de reconstruction, mais je peux avoir l'arbre le temps de reconstruction mis à minuit, et l'arbre est en lecture seule. Notre trafic est faible, de sorte que probablement va être OK.
OriginalL'auteur Charles | 2010-12-16
Vous devez vous connecter pour publier un commentaire.
Par la FindBugs la description des anomalies:
Outre les problèmes de concurrence, cela signifie que toutes les instances dans la JVM sont accède aux mêmes données, et ne serait pas permettre à deux groupes distincts d'instances. Il serait mieux si vous aviez un singleton "gestionnaire" de l'objet et l'a transmis à chacune des instances comme un paramètre de constructeur ou au moins comme un
setManager()
un argument de méthode.Comme pour les problèmes de concurrence: si vous devez utiliser un champ statique, votre champ statique devrait être final, explicite la synchronisation est difficile. (Il y a aussi quelques épineux les aspects si vous sont en cours d'initialisation non définitif des champs statiques, au-delà de mes connaissances de Java, mais je pense que j'ai vu dans le Java casse-têtes livre.) Il y a au moins trois façons de traiter cette question (attention, le code non testé suit, vérifier d'abord avant de l'utiliser):
Utiliser un thread-safe collection, par exemple
Collections.synchronizedList
enroulé autour d'une liste qui n'est pas accessible de toute autre manière.et puis plus tard, quand vous remplacez cette collection, à partir d'un exemple:
Le problème avec cela est que si les deux instances sont en train de faire cette séquence dans le même temps, vous pourriez obtenir:
Instance1: articles.clear();
Instance2: articles.clear();
Instance1: articles.addAll(newItems);
Instance2: articles.addAll(newItems);
et obtenir une liste qui ne répond pas à la classe souhaitée, invariant, à savoir que vous avez deux groupes de newItems dans la liste statique. Si cette méthode ne fonctionne pas si vous êtes centre de l'ensemble de la liste comme une étape, et en ajoutant des éléments comme une deuxième étape. (Si votre instances juste besoin d'ajouter un élément, cependant,
items.add(newItem)
serait en sécurité à utiliser à partir de chaque instance.)Synchroniser l'accès à la collection.
Vous aurez besoin d'un mécanisme explicite pour la synchronisation d'ici. Synchronisé méthodes ne fonctionnent pas parce qu'ils se synchronisent sur "ce", qui n'est pas commun entre les instances. Vous pouvez utiliser:
utilisation AtomicReference
OriginalL'auteur Jason S
Si je comprends le message que vous avez posté de Trouver des Bugs correctement, c'est juste un avertissement.
Si vous souhaitez masquer l'avertissement, de faire des modifications à partir d'une méthode statique. Trouvez des Bugs est en garde car c'est généralement une erreur. Le programmeur pense qu'ils sont en train de changer certaines l'état de l'instance, mais en réalité ils sont en train de changer certaines de l'état qui a un impact sur chaque instance.
OriginalL'auteur Tim Bender
À l'aide de la Singleton modèle de conception est d'une seule façon. Vous ne pouvez avoir qu'une seule instance d'un objet qui contient la valeur que vous voulez, et accéder à cette instance par le biais d'une propriété globale. L'avantage est que, si vous voulez avoir plus d'instances plus tard, il y a moins de modification de code préexistant (puisque vous n'êtes pas à l'évolution des champs statiques à des champs d'instance).
+1 -- c'est la réponse appropriée. En général, les méthodes statiques doivent être apatrides et les champs statiques obsolète, parce qu'il est plus difficile à remplacer, dans les objets pour les tests.
A la question vraiment de synchronisation?
OriginalL'auteur Mehrdad
Vous n'avez pas besoin de supprimer la liste à chaque fois. Comme indiqué ci-dessus, vous devrez composer avec plusieurs threads, mais vous pouvez créer la liste de tableaux une fois, puis utilisez clear() et addAll() méthodes pour nettoyer et remplir de nouveau. FindBugs devrait être tout à fait heureux avec ça parce que vous n'êtes pas un paramètre statique.
gars - n'hésitez pas à puce si il ya un problème avec cette technique 🙂
Une seconde pensée est de conduire les choses à partir de la base de données via hibernate. Afin de ne pas maintenir une liste, hibernate a intégré la mise en cache de sorte qu'il est presque aussi rapide. Si vous mettez à jour les données au niveau base de données (ce qui signifie qu'hibernate ne sais pas), vous pouvez dire à hibernate d'effacer le cache et l'actualisation de la base de données lorsqu'il est ensuite interrogé.
OriginalL'auteur drekka
Vous ne voulez pas le faire. Chaque requête s'exécute dans son propre thread. Si le code est exécuté sur un navigateur d'action modifie la liste, puis deux demandes peuvent éventuellement modifier la liste en même temps, ainsi que de corrompre les données. C'est pourquoi il n'est pas une bonne idée d'accéder aux ressources statiques à partir d'un non-contexte statique, et probablement la raison pour laquelle votre outil est pour vous avertir.
Regardez cette
http://download.oracle.com/javase/6/docs/api/index.html?java/util/concurrent/package-summary.html
surtout la partie sur la façon dont l'ArrayList n'est pas synchronisé. Notez également que le paragraphe I de mentionner a une solution, plus précisément
C'est une façon de le faire. Mais ce n'est pas une bonne idée, notamment parce qu'elle peut être lente. Si ce n'est pas une application commerciale, et vous n'avez pas affaire à un volume élevé, vous pouvez probablement obtenir en ne la rendant pas mieux. Si c'est le type d'application qui ne reçoit que de frapper quelques fois par jour, vous pouvez ignorer l'avertissement, avec la compréhension que le son est possible que quelque chose de mauvais va se passer si deux demandes munge les uns des autres.
Une meilleure solution: Puisque vous avez de la base de données, je voudrais simplement obtenir de l'information à partir de la db que vous en avez besoin, c'est à dire que les demandes proviennent de. Vous pouvez utiliser certaines technologies de mise en cache pour la performance.
La raison pour laquelle je n'aime pas le Pattern Singleton idée est que même si elle fait de l'avertissement à s'en aller, il n'a pas d'adresse fondamentaux de problème de synchronisation, par lui-même. Il y a des thread-safe http://en.wikipedia.org/wiki/Singleton_pattern#Traditional_simple_way_using_synchronization, cependant, qui pourrait fonctionner dans ce cas.
c'est vrai, mais compte tenu de la nature de la question, je ne pense pas que l'OP est de la manipulation de la simultanéité correctement.
En particulier, la statique de la variable doit être définie qu'après la nouvelle liste est (re)construit, et pas pendant qu'il est en cours de construction. Cela ne veut pas éliminer le problème de synchronisation, mais il se rétrécit la fenêtre de contention beaucoup.
OriginalL'auteur hvgotcodes