Comment en attente d'un thread
Je veux lancer un thread pour certains montant fixe de temps. Si elle n'est pas remplie dans le temps, j'ai envie de tuer, de lancer une exception, ou la poignée d'une certaine façon. Comment peut-il être fait?
Une seule façon de faire que j'ai compris de ce fil
est d'utiliser un TimerTask à l'intérieur de la méthode run() du Thread.
Y a de meilleures solutions pour cela?
EDIT: Ajout d'un bounty que j'avais besoin d'une réponse plus claire. Le ExecutorService de code ci-dessous ne résout pas mon problème. Pourquoi devrais-je dormir() après l'exécution (code - je n'ai pas de poignée plus de ce morceau de code)? Si le code est terminé et le sleep() est interrompue, comment cela peut-il être un délai d'attente?
La tâche qui doit être exécutée n'est pas en mon pouvoir. Il peut être n'importe quel morceau de code. Le problème, c'est ce morceau de code peut s'exécuter dans une boucle infinie. Je ne veux pas que cela se produise. Donc, je veux juste pour exécuter la tâche dans un thread séparé. Le parent thread doit attendre jusqu'à ce que le thread des finitions et des besoins de connaître l'état de la tâche (j'.e si elle a expiré ou une exception s'est produite ou si c'est un succès). Si la tâche entre dans une boucle infinie, mon parent fil continue à attendre indéfiniment, ce qui n'est pas une situation idéale.
- EDIT: Ajout d'un bounty que j'avais besoin de plus de réponse claire. le ExecutorService de code ci-dessous ne résout pas mon problème. Pourquoi devrais-je dormir() après l'exécution de mon code? Si le code est terminé et le sleep() est interrompue, comment cela peut-il être un délai d'attente?
- Que
sleep()
était juste un stub pour représenter le "temps long tâche en cours d'exécution". Il suffit de remplacer avec votre tâche réelle 😉 - ... un "temps long tâche en cours d'exécution" qui arrive à répondre à
interrupt()
appels sur son fil... pas tout "blocage", les appels, comme j'ai essayé de préciser dans ma réponse. Les spécificités de la tâche que vous essayez d'abort faire une énorme différence dans l'approche qui devrait être utilisé. Plus d'informations sur la tâche serait utile. - Si ces réponses ne sont pas de résoudre le problème, alors je suppose que plus de détails/code devraient vous aider à répondre.
- Ces threads que vous voulez de limite dans le temps; ils blocage des appels, ou sont-ils dans certains boucle où vous pouvez facilement vérifier certaines variables pour voir si il est temps de cesser de fumer?
- la réponse, c'est maintenant plus clair?
Vous devez vous connecter pour publier un commentaire.
En effet plutôt l'utilisation d'
ExecutorService
au lieu deTimer
, voici un SSCCE:Jouer un peu avec les
timeout
argument enFutur#get()
méthode, par exemple une augmentation à 5 et vous verrez que le thread se termine. Vous pouvez intercepter le délai d'attente dans l'catch (TimeoutException e)
bloc.Mise à jour: de clarifier conceptuel de l'incompréhension, de l'
sleep()
est pas nécessaire. Il est seulement utilisé pour le SSCCE/à des fins de démonstration. Il suffit de ne votre long de la tâche en cours d'exécution dans le lieu desleep()
. À l'intérieur de votre longue tâche en cours d'exécution, vous devriez vérifier si le fil n'est pas interrompu comme suit:Thread.sleep(4000)
avec quelques autres longue instruction et l'exemple ne fonctionne pas. En d'autres termes, cet exemple de travail uniquement si leTask
est conçu pour comprendreThread.isInterrupted()
de changement de statut.executor.shutdownNow()
, vous pouvezwhile (true) {try {if (executor.awaitTermination(1, TimeUnit.SECONDS)) break;} catch (InterruptedException ie) {}}
, en fait depuis l'arrêt de la tâche peut prendre un certain temps.Il n'y a pas 100% fiable façon de faire n'importe quelle tâche. La tâche doit être écrit avec cette capacité à l'esprit.
De base des bibliothèques Java comme
ExecutorService
annuler les tâches asynchrones avecinterrupt()
appels sur le thread de travail. Ainsi, par exemple, si la tâche contient une sorte de boucle, vous devriez vérifier son interrompre le statut de à chaque itération. Si la tâche est de faire des opérations d'e/S, ils devraient être interruptible trop—et de mettre en place peut être délicat. Dans tous les cas, gardez à l'esprit que le code a activement vérifier les interruptions; définition d'une interruption n'est pas nécessairement de faire quoi que ce soit.Bien sûr, si votre tâche est simple boucle, vous pouvez simplement vérifier l'heure actuelle à chaque itération et d'abandonner lorsqu'un délai spécifié s'est écoulé. Un thread de travail n'est pas nécessaire dans ce cas.
execute()
méthode de l'interface parent,Executor
peut exécuter une tâche dans le thread appelant. Il n'y a pas de déclaration similaire pour lesubmit()
méthodes deExecutorService
que le retourFuture
instances. L'implication du service est qu'il y a des threads de travail qui doivent être nettoyés par l'arrêt, et que les tâches sont exécutées de manière asynchrone. Cela dit, il n'y a rien dans le contrat qui dit que leExecutorService
est interdite à partir de l'exécution des tâches en soumettant fil; ces garanties viennent de la mise en œuvre des Api, commeExecutors
usines.Envisager d'utiliser une instance de ExecutorService. Les deux
invokeAll()
etinvokeAny()
méthodes sont disponibles avec untimeout
paramètre.Le thread se bloque jusqu'à ce que la méthode est terminée (pas sûr si cela est souhaitable), soit parce que la tâche(s) terminé normalement ou que le délai a été atteint. Vous pouvez inspecter le retour de l'
Future
(s) pour déterminer ce qui s'est passé.BalusC dit:
Mais si vous remplacez
Thread.sleep(4000);
avecfor (int i = 0; i < 5E8; i++) {}
alors il ne compile pas, parce que le vide de la boucle n'est pas à jeter unInterruptedException
.Et pour le fil pour être interruptible, il doit lever une
InterruptedException
.Cela semble être un grave problème pour moi. Je ne vois pas comment adapter cette réponse de travailler avec un travail de longue haleine.
Édité à ajouter: je reasked cela comme une nouvelle question: [ interrompre un thread après un temps fixe, a-t-elle à jeter InterruptedException? ]
En supposant que le code de thread est hors de votre contrôle:
De la Java la documentation mentionnés ci-dessus:
Ligne Du Bas:
Assurez-vous que tous les threads peut être interrompue, ou autre vous avez besoin de connaissances spécifiques sur le fil - un peu comme un drapeau à définir. Peut-être que vous pouvez exiger que la tâche sera donné avec le code nécessaire pour l'arrêter - définir une interface avec un
stop()
méthode. Vous pouvez également vous avertir lorsque vous avez échoué à arrêter une tâche.Je pense que vous devriez jeter un coup d'oeil à la bonne simultanéité des mécanismes de gestion (threads s'exécutant dans une boucle infinie n'est pas bon en soi, btw). Assurez-vous de lire un peu sur le "tuer" ou "arrêt" Threads sujet.
Ce que vous décrivez,le son à la manière d'un "rendez-vous", de sorte que vous pouvez prendre un coup d'oeil à la CyclicBarrier.
Il y a peut être d'autres constructions (comme l'utilisation de CountDownLatch par exemple) qui peut résoudre votre problème (un thread en attente avec un délai d'attente pour le le loquet, les autres doivent compter que le loquet s'il a terminé son travail, ce qui permettrait de sortir votre premier fil que ce soit après un délai d'attente ou lorsque le loquet compte à rebours est invoquée).
Je recommande habituellement de deux livres dans ce domaine: La Programmation simultanée en Java et Java de la Simultanéité dans la Pratique.
J'ai créé une classe d'aide juste pour cela, il y a quelques temps. Fonctionne très bien:
Il est appelé comme ceci:
Je post vous un morceau de code qui montrent une façon de résoudre le problème.
Comme exemple je suis en train de lire un fichier.
Vous pouvez utiliser cette méthode pour une autre opération, mais vous avez besoin de implémente le kill() la méthode de sorte que l'opération principale sera interrompu.
espère que cela aide
Ce qui concerne
L'extrait de code suivant va démarrer une opération dans un thread séparé, puis attendre jusqu'à 10 secondes de la fin de l'opération. Si l'opération ne se termine pas dans le temps, le code sera tentative pour annuler l'opération, puis continuer son petit bonhomme de chemin. Même si l'opération ne peut être annulée facilement, le parent thread va pas attendre que l'enfant thread pour résilier.
La
getExecutorService()
méthode peut être appliquée dans un certain nombre de façons. Si vous n'avez pas d'exigences particulières, vous pouvez simplement appelerExecutors.newCachedThreadPool()
pour la mise en pool de threads avec pas de limite supérieure sur le nombre de threads.SomeClass
etFuture
?Une chose que je n'ai pas vu mentionné est que tuer des threads est généralement une Mauvaise Idée. Il y a des techniques pour faire filetée méthodes proprement abortable, mais c'est différent de simplement de tuer un thread après un délai d'attente.
Le risque avec ce que tu suggère, c'est que vous ne savez probablement pas ce que l'état, le thread va être lorsque vous tuer, donc vous risquez d'introduire une instabilité. Une meilleure solution est de s'assurer que votre fileté code n'accrochez pas de lui-même, ou répondra parfaitement à une demande d'annulation.
Voici ma vraiment simple à utiliser classe d'assistance pour exécuter ou appel morceau de code Java 🙂
Ceci est basé sur l'excellent réponse de BalusC
Grande réponse par BalusC de l':
mais Juste pour ajouter que le délai lui-même ne pas interrompre le fil lui-même. même si vous êtes à vérifier avec le while(!Fil de discussion.interrompu()) dans votre tâche. si vous voulez vous assurer que le thread est interrompu, vous devez également veiller à l'avenir.annuler() est appelée lorsque l'exception délai est prise.
Je pense que la réponse dépend principalement de la tâche elle-même.
Si la première réponse est oui et le second l'est pas, vous pouvez le garder aussi simple que cela:
Si ce n'est pas une option, veuillez limiter vos exigences - ou de montrer un peu de code.
Je cherchais un ExecutorService qui peuvent interrompre toutes expiré Runnables exécuté par elle, mais n'en trouva aucun. Après quelques heures, j'ai créé un comme ci-dessous. Cette classe peut être modifiée pour améliorer la robustesse.
Utilisation:
Maintenant , l répondre à une question de ce genre. Il arrive à décoder l'image. Le processus de décodage prend trop de temps que l'écran de garder le noir. l'ajout d'un temps de controler: quand le temps est trop long, une fenêtre pop up à partir du Thread courant.
Ce qui suit est la diff:
J'ai eu le même problème. Donc, je suis venu avec une simple solution de ce genre.
Garantit que si le bloc ne s'est pas exécuté dans le délai imparti. le processus se termine et renvoie une exception.
exemple :
Dans la solution donnée par la BalusC, le thread principal va rester bloquée pendant la période de délai d'attente. Si vous disposez d'un pool de threads avec plus d'un fil, vous aurez besoin du même nombre de threads supplémentaires qui seront à l'aide de L'avenir.get(délai long,TimeUnit unit) de blocage d'appel d'attendre et de fermer le thread si elle dépasse le délai d'attente.
Une solution générique à ce problème est de créer un ThreadPoolExecutor Décorateur qui peut ajouter le délai d'attente de la fonctionnalité. Ce Décorateur classe devrait créer autant de threads que ThreadPoolExecutor a, et tous ces fils doivent être utilisés qu'à patienter et à proximité de la ThreadPoolExecutor.
La classe générique doit être mis en œuvre comme ci-dessous:
Ci-dessus décorateur peut être utilisé comme ci-dessous: