Pregunta

Cuando desarrollé una pieza de software (académico) usando Java, me vi obligado a usar una API que estaba bastante mal implementada. Esto significa que las llamadas a esta API para un cierto conjunto de datos de entrada a veces nunca volverían. Esto debe haber sido un error en el software ya que los algoritmos que ofrecía eran deterministas, y a veces terminaría en un conjunto de datos, a veces se encontraría con un bucle infinito en el mismo conjunto de datos ...

Sin embargo, arreglar la API o volver a implementarla simplemente estaba más allá del alcance. Incluso tenía la fuente, pero la API dependía en gran medida de otras API que estaban indocumentadas y sin fuente y que para cuando desaparecieron de la web (¿o nunca estuvieron allí?). Por otro lado, esto '' malo '' API fue el único que resolvió el problema específico que tenía, así que realmente tuve que seguir con él.

La pregunta es: ¿cuál es la forma más limpia de tratar con una API que se comporta así, bueno, desagradable? Cuando me enfrenté a este problema, decidí poner las llamadas a la API en un hilo separado. Otro hilo verificaría ocasionalmente si este hilo había terminado. Si hubiera pasado una cierta cantidad de tiempo, mataría el hilo de procesamiento usando Thread # stop () y comenzaría el procesamiento nuevamente, con la esperanza de que vuelva la próxima vez. Ahora, sé (y sabía en ese entonces) que este método está en desuso y no debe usarse. Pero en este contexto académico era aceptable que el software potencialmente se ejecute en un estado indefinido en lugar de que se bloquee.

Tampoco era aceptable ignorar el hilo de procesamiento que se había ejecutado en un bucle infinito porque hacía algunas operaciones bastante intensivas de CPU que ralentizarían significativamente la máquina del usuario.

Otra forma en la que no intenté es iniciar el procesamiento en un proceso separado en lugar de un subproceso, porque un subproceso puede eliminarse sin poner el software en un estado inconsistente. ¿O podría la nueva clase SwingWorker (que aún no estaba disponible) haber hecho el trabajo? Tiene un método cancel () , pero los documentos dicen que " Intenta cancelar la ejecución de esta tarea " , por lo que tampoco parece un enfoque confiable .

¿Fue útil?

Solución

Recomendaría el uso de un proceso separado. Esencialmente, no hay una forma segura de que un hilo elimine un segundo hilo en Java a menos que el segundo hilo verifique periódicamente si se ha interrumpido.

La solución ideal sería usar aislamientos. Un aislamiento es esencialmente una máquina virtual privada con la que una aplicación Java puede crear, administrar y comunicarse. En particular, la aplicación principal puede matar de forma segura un aislado y todos sus hilos.

Referencia: JSR-000121 Especificación de API de aislamiento de aplicaciones - Versión final

El problema es encontrar una JVM que admita aislamientos.

Otros consejos

Soy un gran admirador de los procesos separados para este tipo de cosas.

Genera un subproceso y espera los resultados.

Si la API no es determinista, coloque el hilo del temporizador en un contenedor que convierta la API incorrecta en un programa principal.

De esa manera, el subproceso siempre termina dentro del tiempo dado. O produce un resultado útil o un código de salida del sistema que indica una falla.

Ambas respuestas de @ S.Lott y @Stephen C son acertadas con respecto a cómo manejar este tipo de situación, pero me gustaría agregar que en un entorno no académico, también debería buscar reemplazar el API tan pronto como sea práctico. En situaciones en las que hemos estado encerrados en una API incorrecta, generalmente a través de la elección de una solución vendida por otros motivos, he trabajado para reemplazar la funcionalidad con la mía con el tiempo. Sus clientes no van a ser tan tolerantes como su profesor, ya que en realidad tienen que usar su software (¡o no!) En lugar de simplemente calificarlo.

Ciertamente, hay situaciones en las que el uso de cinta adhesiva es una opción adecuada para resolver un problema. Sin embargo, cuando da como resultado un comportamiento tan pobre como lo describe, es mejor no confiar demasiado en él y comenzar a trabajar en una reparación real.

Lo mejor sería hacer una nueva implementación de la API en cuestión. Sin embargo, como usted dice, es una solución muy pesada y probablemente fuera de alcance.

Lo siguiente mejor sería envolver la API si es posible. Básicamente, si puede determinar de antemano de qué se trata el conjunto de datos que causa la falla, podría rechazar las llamadas para garantizar el determinismo. No parece que esto funcione para usted tampoco, ya que sugiere que repetir una llamada con el mismo conjunto de datos a veces terminará cuando se haya repetido infinitamente en una invocación previa.

Dadas las opciones anteriores, las anteriores no están disponibles:
Creo que su solución de hilo actual es la mejor de las malas elecciones . Acelerar un proceso para una llamada al método parece demasiado pesado para ser aceptable desde el punto de vista del rendimiento, incluso si es más seguro que usar hilos. Thread.stop () es muy peligroso, pero si evita religiosamente cualquier bloqueo, puede salirse con la suya.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top