Question

Lorsque j'ai développé un logiciel (académique) en Java, j'ai été contraint d'utiliser une API plutôt mal implémentée. Cela signifie que les appels à cette API pour un certain ensemble de données d'entrée ne seraient parfois jamais renvoyés. Cela devait être un bogue dans le logiciel car les algorithmes proposés étaient déterministes, et parfois il se terminait sur un ensemble de données, parfois il se heurtait à une boucle infinie sur le même ensemble de données ...

Cependant, réparer l'API ou le réimplémenter était tout simplement hors de portée. J'avais même le code source, mais l'API reposait largement sur d'autres API non documentées et sans source, qui avaient disparu du Web (ou n'y étaient jamais allées?). En revanche, ce "mauvais" API était le seul à résoudre le problème spécifique que je rencontrais et je devais vraiment m'en tenir à cela.

La question qui se pose est la suivante: quel est le moyen le plus propre de traiter une API qui se comporte de la sorte, méchant? Lorsque j'ai rencontré ce problème, j'ai décidé de placer les appels à l'API dans un thread séparé. Un autre thread vérifiait alors occasionnellement si ce thread s'était terminé. Si un certain temps s'était écoulé, je mettrais fin au processus de traitement à l'aide de Thread # stop () et recommencerais le traitement, en espérant qu'il reviendrait la prochaine fois. Maintenant, je sais (et savais à l'époque) que cette méthode est obsolète et ne doit pas être utilisée. Mais dans ce contexte académique, il était acceptable de laisser le logiciel potentiellement entrer dans un état non défini au lieu de le bloquer.

Il était également inacceptable d'ignorer simplement le processus de traitement qui s'était exécuté dans une boucle infinie, car il effectuait des opérations très gourmandes en ressources processeur qui ralentiraient considérablement la machine de l'utilisateur.

Une autre façon que je n'ai pas essayée est de démarrer le traitement dans un processus séparé au lieu d'un thread, car un sous-processus peut être tué proprement sans mettre le logiciel dans un état incohérent. Ou bien la nouvelle classe SwingWorker (qui n'était pas encore disponible) a-t-elle fait le travail? Il a une méthode cancel () , mais la documentation indique qu'elle "Tentative d'annuler l'exécution de cette tâche" , de sorte qu'elle ne ressemble pas non plus à une approche fiable. .

Était-ce utile?

La solution

Je recommanderais l'utilisation d'un processus séparé. Il n’existe essentiellement aucun moyen sûr pour un thread de tuer un second thread en Java, à moins que le second thread ne vérifie périodiquement qu’il a été interrompu.

La solution idéale serait d’utiliser des isolats. Un isolement est essentiellement une machine virtuelle privée qu'une application Java peut créer, gérer et avec laquelle communiquer. En particulier, l’application parent peut tuer en toute sécurité un isolat et tous ses threads.

Référence: Spécification de l'API d'isolation d'application JSR-000121 - Version finale

Le problème consiste à trouver une machine virtuelle qui prend en charge les isolements.

Autres conseils

Je suis un grand fan des processus séparés pour ce genre de chose.

Lancez un processus secondaire et attendez les résultats.

Si l'API n'est pas déterministe, placez le thread du minuteur dans un wrapper qui transforme l'API défectueuse en programme principal.

Ainsi, le sous-processus se termine toujours dans le temps imparti. Il en résulte un résultat utile ou un code de sortie système indiquant un échec.

Les réponses de @ S.Lott et de @Stephen C sont claires quant à la façon de gérer ce type de situation, mais je voudrais ajouter que dans un environnement non universitaire, vous devriez également chercher à remplacer le API dès que possible. Dans les cas où nous avons été enfermés dans une mauvaise API, généralement en choisissant une solution vendue pour d'autres raisons, je me suis efforcé de remplacer cette fonctionnalité par la mienne au fil du temps. Vos clients ne seront pas aussi tolérants que votre professeur car ils doivent réellement utiliser votre logiciel (ou non!) Au lieu de simplement le noter.

Il existe certainement des situations où l’utilisation de ruban adhésif en toile est un choix approprié pour résoudre un problème. Toutefois, lorsque le comportement que vous décrivez est mauvais, il est préférable de ne pas trop compter dessus et de commencer à travailler sur une vraie réparation.

La meilleure solution consiste à réimplémenter l'API en question. Cependant, comme vous le dites, c'est une solution très lourde et probablement hors de portée.

La bonne nouvelle serait d'encapsuler l'API si possible. Fondamentalement, si vous pouvez déterminer à l’avance ce qui cause l’échec au niveau des jeux de données, vous pouvez rejeter les appels pour garantir le déterminisme. Il ne semble pas que cela fonctionne pour vous non plus, car vous suggérez que la répétition d'un appel avec le même jeu de données se termine parfois lorsqu'elle a été mise en boucle à l'infini lors d'une invocation antérieure.

Étant donné que les options ci-dessus ne sont pas disponibles:
Je pense que votre solution de thread actuelle est le meilleur des mauvais choix . Relancer un processus pour un appel de méthode semble beaucoup trop lourd pour être acceptable du point de vue des performances, même s'il est plus sûr que d'utiliser des threads. Thread.stop () est très dangereux, mais si vous empêchez religieusement tout verrouillage, vous pouvez vous en sortir.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top