Les meilleures pratiques pour l'enregistrement de Java à partir de plusieurs threads?
Je veux avoir un journal de diagnostic qui est produite par plusieurs tâches de gestion des données. Ces tâches peuvent être dans plusieurs threads. Chaque tâche doit écrire un élément (avec éventuellement des sous-éléments) pour le journal; entrer et sortir rapidement. Si c'était une seule tâche situation, je voudrais utiliser XMLStreamWriter comme il semble être le meilleur match pour des raisons de simplicité, fonctionnalité sans avoir à tenir un ballon document XML en mémoire.
Mais ce n'est pas une simple tâche de la situation, et je ne suis pas sûr de savoir comment mieux faire sûr que c'est "thread-safe", où "thread-safe" dans cette application signifie que chaque journal élément doit être écrit dans le journal correctement et en série (l'un après l'autre et non entrelacé en quelque sorte).
Des suggestions? J'ai une vague intuition que le chemin à parcourir est d'utiliser une file d'attente de journal éléments (avec chacune d'elles pouvant être produit rapidement: mon application est en train de faire le travail réel que les performances sensibles), et avoir un thread qui gère le journal éléments et les envoie à un fichier de journalisation de ne pas interrompre les producteurs.
La journalisation n'est pas nécessairement le XML, mais je ne veux pas qu'il soit structuré et lisible à la machine.
edit: j'ai mis "thread-safe" entre guillemets. Log4j semble être le choix évident (nouveau pour moi, mais les vieux de la communauté), pourquoi réinventer la roue...
- J'ai le même problème, mais n'a pas besoin d'afficher le journal en temps réel (seulement après que tous les threads d'exécution). Ma solution est d'ajouter un système de temps au début de chaque message, et de les trier sur le temps.
- Temps de système n'est pas fiable, après tout -, certaines opérations sont si proches qu'ils ont le même temps en millisecondes. Le tri peut mener à un changement de l'ordre. Donc, une autre chose que j'ai essayé était à l'aide de Colllections.synchronizedList() pour envelopper une liste de tableaux de Chaînes de messages. L'ajout de la chaîne d'horodatage montre que même de cette manière n'est pas parfait. Certains messages dans mon cas, ont été de l'ordre (par un ou deux millisecondes), mais cela est probablement dû à la mise en attente du délai pour l'appel add() de la synchronisation de la liste.
Vous devez vous connecter pour publier un commentaire.
Utiliser un enregistrement cadre des, telles que Log4j.
Je pense que vous êtes sur la mauvaise voie. Vous dites “thread-safe” mais vous avez réellement dire “sérialisé”. Thread-safe signifie qu'un thread ne sera pas interférer avec des données provenant d'autres fil. La plupart du temps, le filetage problèmes sont résolus à l'avance et vous ne devriez pas vous inquiéter à ce sujet juste pour l'enregistrement de souci. Par exemple, si vous écrivez:
Vous devez vous assurer que mavariable n'a pas été modifié par un autre thread à partir du moment où le calcul (première ligne) a été réalisée, mais avant l'enregistrement de la méthode a été appelée. Si cela se produit, vous allez vous connecter sale valeur qui n'a pas été utilisé pour effectuer l'opération, mais la valeur qui a été affecté par un autre thread. C'est généralement pris en charge; par exemple local (au niveau de la méthode) de la variable ne peut pas être changé par un autre thread. De toute façon, si vous avez à vous inquiéter à ce sujet lors de la connexion, que 99% que votre programme a de graves problèmes de threading déjà.
Tous les grands de la journalisation des cadres sont par eux-mêmes “thread-safe” ce qui signifie qu'ils peuvent être déployés dans des environnements multithreads et n'aura pas de problèmes d'affichage similaire à celle décrite ci-dessus à l'interne.
Obtenir des traces apparaissent dans les journaux afin qu'ils se produisent est en fait habituellement appelé “sérialisation” des appels. La sérialisation des écritures de journal sera un important goulot d'étranglement des performances sur toute application multithread. Si vous utilisez la journalisation cadre, comme log4j, les traces de tous les threads vont apparaître en seul endroit plus ou moins dans l'ordre où elles se produisent. Cependant, une colonne est généralement le nom du Thread, de sorte que vous pouvez facilement filtrer vos données de journal par fil; chaque thread va enregistrer ses données dans l'ordre chronologique. Consultez ce lien:
http://logging.apache.org/log4j/1.2/faq.html#1.7
Enfin, si la sérialisation des écritures de journal est ce que vous avez vraiment besoin, alors vous pouvez utiliser un certain type de structure, comme java.util.de façon concomitante.BlockingQueue pour acheminer vos messages.
Utilisation logback-classique. Il s'agit d'une nouvelle et meilleure mise en œuvre de log4j.
J'ai tendance à utiliser SLF4J sur le dessus de Log4J. Le paramétrable de journalisation fonctionnalité est particulièrement intéressante si vous allez avoir beaucoup de journalisation des déclarations qui peuvent ainsi s'éteint dans un environnement de production.
Il peut également s'exécuter sur le dessus de java.util.l'exploitation forestière ou de l'utilisation de son propre simple de sortie.
Vous pouvez utiliser la synchronisation des mécanismes (comme un moniteur ou un semaphor) pour s'assurer, qu'un journal demande est traitée avant d'accepter l'autre. Cela pourrait être caché dans le code de l'appel de la journalisation des routines.
et si vous n'êtes pas heureux avec le résultat que vous pouvez écrire votre propre Appender, Filtre, que ce soit pour le modifier il suffit d'écrire. Donc, vous pourriez faire de même certains de la mise en cache pour réorganiser les entrées, bien que je ne dis pas que c'est une bonne idée.
Utiliser un enregistrement cadre qui met en place une certaine forme de le NDC modèle, comme Log4J.
log4j est et a été la norme pour l'enregistrement de java depuis de nombreuses années. Mais si vous n'avez pas envie de dépendance externe puis le java.util.la journalisation paquet fournit une solution acceptable.
J'ai eu un problème similaire et la mise en œuvre des exigences spéciales des journaux uniquement. Ma solution a été:
J'ai pris un
blockinglinkedqueue
avec la taille de*2
de l'application de la circulation/min.Tous les threads de mettre l'objet dans la file d'attente et termine le travail.
Séparé
Log-Writer
thread de prendre la tête de l'objet à partir de la file d'attente et de l'écriture àlog4j
fichier en utilisant un appender. Cette appender n'a pas été utilisé pour systemlogs.Cela garantit que les journaux sont écrits en série et sont toujours dans l'ordre.
Cela n'affectera pas les performances de l'application depuis le journal d'écriture est un tout autre processus et de ne pas créer un goulot d'étranglement.
Vous pouvez également utiliser
aysncappender
delog4j
.Si vous deviez, vous pouvez rouler votre propre .. en utilisant un seul écrivain unique/lecteur FIFO ou les files d'attente.
Développer vous-même dans un "thread-safe" chemin n'est pas trivial, donc vous devriez vraiment utiliser un existant de journalisation qui est thread-safe. Le plus couramment utilisé est Log4J, qui est thread-safe (voir la FAQ).
C'est une vieille question, mais voici ma solution à l'aide de Log4J par programmation.
LogFactory classe
Puis à procéder à l'initialisation de l'enregistreur utiliser l'approche suivante