Comment puis-je m'assurer qu'une méthode est appelée une seule fois par plusieurs threads?
Je avoir la structure suivante:
public void someMethod(){
//DO SOME STUFF
try{
doSomeProcessing();
}
catch (Exception e){
loadSomeHeavyData();
doSomeProcessing();
}
}
La méthode someMethod
peut être appelé simultanément par plusieurs threads. Le doSomeProcessing
peut lever une exception (c'est l'utilisation de certaines données dans le backend qui pourraient devenir obsolètes).
Si une exception est levée puis loadSomeHeavyData();
fait un peu tâche qui prend beaucoup de temps, disons "mises à jour" toutes les données actuelles et je suis en mesure d'appeler doSomeProcessing();
.
Problème: Comment puis-je m'assurer que loadSomeHeavyData();
est appelé seulement une fois? Si j'ai mis quelques atomique drapeau à l'entrée de loadSomeHeavyData();
alors je ne peux pas être sûr si cela devrait être effacé.
Comment puis-je résoudre ce problème? Juste une remarque: je ne peux pas modifier doSomeProcessing();
que c'est une API externe et je suis en utilisant le décorateur modèle à utiliser.
source d'informationauteur Jim
Vous devez vous connecter pour publier un commentaire.
Votre
loadSomeHeavyData
méthode pourrait utiliser un mécanisme de blocage de faire tous les threads en attente jusqu'à ce qu'il ait terminé sa mise à jour, mais seulement de laisser l'un d'entre eux ne fait de la mise à jour:Note mes hypothèses:
doSomeProcessing
une deuxième fois avec des données mises à jourloadSomeHeavyData
une fois, jamais - si non, vous aurez besoin de réinitialiser le drapeau et la CountdownLatch (qui serait alors sans doute pas être le mécanisme le plus approprié).MODIFIER
Votre dernier commentaire indique que vous voulez l'appeler
loadSomeHeavyData
plus d'une fois, mais pas plus d'une fois à un moment.À l'aide de la
synchronized
mot-clé:Vous assurer que seul un thread entre dans à un moment.
Pour assurer que la méthode est appelée qu'une seule fois, il n'y a pas de langue spéciale, vous pouvez créer une variable statique de type booléen qui est vrai par le premier thread entrer dans la méthode. Lors de l'appel de la méthode, vérifiez toujours que le drapeau:
L'une des solutions pourrait être de créer une file d'attente dans laquelle chaque fil met sa demande d'appel
loadSomeHeavyData
. lorsque aucun. des demandes d'atteindre un threashold, bloquer l'exécution desomeMethod
et appelloadSomeHeavyData
et effacer la file d'attente.Pseudo-code peut ressembler à ceci:
Que je comprends de votre question que vous devez vous charger des données dans une imprévisible, mais limitée intervalle de temps. Il y a trois façons possibles de le faire:
1) Vous pouvez entourer votre appel à loadSomeHeavyData avec une instruction if qui contrôle l'accès à la méthode.
2) Vous pouvez changer votre méthode pour gérer le flux de contrôle (décision de mise à jour ou pas)
3) Écrire une mise à jour du thread et de le laisser faire le travail pour vous
Les deux premières solutions de rechange peut utiliser un externe valeur booléenne ou de générer un booléen décision à l'aide de la timedelta entre le dernier appel et le courant du temps d'appel.
Troisième solution serait un temps de thread qui s'exécute toutes les n secondes/minutes et de charger les données lourdes.
Nous avons écrit une bibliothèque qui comprend un utilitaire paresseusement de chargement/appel d'une méthode. Il garantit un usage unique de la sémantique et préserve toutes les exceptions lancées comme vous le souhaitez.
Utilisation est simple:
Tous les blocs de threads sur le
get()
et d'attendre que le producteur thread (le premier de l'appelant).