8
votes

Java: Singlethreadschedledexecutor & java.Util.ConCurrent.ReçàExceptionExceptionException

J'ai ce problème, j'ai xxx

et tâche créé tous les 50 milllisecondes: xxx

mytask prend parfois un certain temps pour compléter (comme 2-3 secondes environ), mais NewsinglethreadscheduledExecutor garantit que le prochain mytask planifié attendra que le courant actuel se termine.

Cependant, je reçois cette erreur à partir de temps Pour le temps:

Exécuter: java.util.concurrent.reçudexecutionException

Que dois-je faire? Merci


5 commentaires

S'il vous plaît soyez plus précis sur ce que vous entendez par «de temps en temps». Cette exception ne devrait être jetée qu'au moment de l'appelant Execute () sur l'exécuteurService.


En fait, RejetedExecutionException est lancée par Executor.scheduleatfixeDrate ()


@Andrey, vous devez nous donner de manière significative plus d'informations, en commençant par une trace de pile montrant l'exception.


@Jim, oui, je veux dire "pour le moment le travail est soumis", par opposition à "de temps à autre" :)


Oui, parfois rejetéExceptionException est jeté lorsque j'appelle ScheduleAtfixeDrate (pas toujours, mais je suppose qu'il commence à jeter l'exception lorsque mon Mytask prend plus de temps pour terminer que toujours).


3 Réponses :


4
votes

Cette exception sera lancée lorsque:

  1. Vous avez fermé l'exécuteur
  2. Les limites de l'exécuteur de l'exécuteur de sa file d'attente de travail ou des filets maximaux ont été dépassés.

    Je suppose que ce dernier se passe. Lorsque vous exécutez votre tâche et qu'il faut beaucoup de temps, les tâches programmées ultérieures ne peuvent pas être exécutées car il n'y a pas assez de threads disponibles dans la piscine.

    soit:

    1. Utilisez une plus grande taille de piscine ou utilisez CachedTheadpool
    2. Modifiez la stratégie de rejet en par exemple, utilisez ThreadPoolEcutor.callerrunspolicy
    3. Créez un exécuteur séparé pour exécuter les tâches à long terme et exécutez-les depuis votre tâche planifiée. En réalité, vous pouvez le faire en utilisant la même instance exécutante à condition que vous augmentez la taille de la piscine.

      Voir aussi threadpoolEcutor Javadoc < / a>


1 commentaires

Comment utiliser CachedTheadpool dans ma situation? Executor.ScheduleatFixeDrate (Mytask, 0, 50, TimeUnit.Milliseconds); Comment est-il possible de changer la politique de rejet threadpoolexecutive? Merci



15
votes

considère ce que fait l'exécutif. Il gère une seule tâche toutes les 50 millisecondes, selon vos instructions. En supposant que cette tâche prend moins de 50 millisecondes à courir, tout va bien. Cependant, chaque souvent, il faut 2-3 secondes pour courir. Lorsque cela se produit, l'exécuteur exécutant essaie toujours d'exécuter toutes les 50 millisecondes, mais comme il n'a qu'un seul fil, il ne peut pas et rejette ces exécutions qui sont déclenchées pendant que votre tâche de longue date est toujours en cours. Cela provoque l'exception que vous voyez.

Vous avez deux choix pour résoudre ce problème (en supposant que vous souhaitiez rester avec un seul fil):

  1. Utilisez SchecheWithFixedDelay plutôt que planifiantAtfixeDrate . Si vous lisez soigneusement Javadoc, vous verrez que SchecheWithFixedDelay attendra 50 millisecondes entre la finition d'une tâche et le début de la prochaine, il ne "se chevauchera jamais", même si l'un d'entre eux prend beaucoup de temps. En revanche, SchedgeAreatFixeDrate tentera d'exécuter toutes les 50 millisecondes, quelle que soit la durée de chacune de chacune.

  2. Modifiez la manière dont l'exécuteur traite les défaillances à exécuter. La valeur par défaut consiste à enregistrer une exception, mais vous pouvez le dire de l'ignorer, par exemple. Jetez un coup d'œil aux sous-classes de java.util.concurrent.reçudexechargerdler , par exemple interrompupolicy , qui dépose simplement silencieusement la tâche qui ne peut pas être exécutée. Vous pouvez les utiliser en construisant directement planifiez planchedHeadpoolEcutor et en passant dans le gestionnaire au constructeur, plutôt que d'utiliser le exécutants classe d'usine.

    L'option Suspective (1) est ce que vous voulez.


1 commentaires

@skaffman: En fait, c'est exactement le contraire de ce que vous avez dit en 1. :) Javadoc: ScheduleAtfixeDrate: Si une exécution de cette tâche prend plus de temps que sa période, les exécutions ultérieures peuvent commencer tardivement, mais ne seront pas exécutés simultanément