Подтвердить что ты не робот

Как изолировать вашу программу от вызовов к "плохому" API?

Когда я разработал часть (академического) программного обеспечения с использованием Java, я был вынужден использовать API, который был довольно плохо реализован. Это означает, что вызовы этого API для определенного набора входных данных иногда никогда не возвращаются. Это, должно быть, было ошибкой в ​​программном обеспечении, поскольку предлагаемые алгоритмы были детерминированными, а иногда и заканчивались на наборе данных, иногда он запускался в бесконечный цикл на одном наборе данных...

Тем не менее, исправление API или переопределение его было просто вне сферы действия. У меня даже был источник, но API в значительной степени полагался на другие API, которые были недокументированы и без источника, и к тому времени исчезли из Интернета (или никогда там не были?). С другой стороны, этот "плохой" API был единственным, кто решил конкретную проблему, которую я имел, поэтому мне действительно пришлось придерживаться ее.

Вопрос: какой самый чистый способ иметь дело с API, который ведет себя так, ну, противно? Когда я столкнулся с этой проблемой, я решил поместить вызовы в API в отдельный поток. Затем другой поток иногда проверял, завершился ли этот поток. Если прошло определенное количество времени, я бы убил поток обработки с помощью Thread#stop() и снова начал обработку, надеясь, что он вернется в следующий раз. Теперь я знаю (и знал тогда), что этот метод устарел и не должен использоваться. Но в этом академическом контексте было приемлемо, чтобы программное обеспечение потенциально запускалось в состояние undefined вместо того, чтобы сбой.

Было также неприемлемо просто игнорировать поток обработки, который запущен в бесконечный цикл, потому что он выполнял некоторые довольно интенсивные операции с процессором, которые значительно замедляли работу пользователя.

Другой способ, который я не пытался, - начать обработку в отдельном процессе, а не в потоке, потому что подпроцесс можно убить чисто, не помещая программное обеспечение в непоследовательное состояние. Или новый класс SwingWorker (который еще не был доступен) выполнил эту работу? Он имеет метод cancel(), но документы говорят, что он "пытается отменить выполнение этой задачи", поэтому он не похож на надежный подход.

4b9b3361

Ответ 1

Я бы рекомендовал использовать отдельный процесс. По сути, нет безопасного пути для одного потока, чтобы убить второй поток на Java, если только второй поток периодически проверяет, не прервана ли она.

Идеальное решение - использовать изоляты. Изоляция по существу является частной виртуальной машиной, с которой Java-приложение может создавать, управлять и обмениваться данными. В частности, родительское приложение может безопасно убить изоляцию и все ее потоки.

Ссылка: JSR-000121 Спецификация API изоляции приложений - окончательная версия

Проблема заключается в поиске JVM, который поддерживает Isolates.

Ответ 2

Я большой поклонник отдельных процессов для такого рода вещей.

Создайте подпроцесс и дождитесь результатов.

Если API не является детерминированным, поместите поток таймера в оболочку, который превращает плохой API в основную программу.

Таким образом, подпроцесс всегда заканчивается в течение данного времени. Он либо дает полезный результат, либо код выхода системы, который указывает на сбой.

Ответ 3

Как ответы @S.Lott, так и @Stephen C касаются того, как справиться с такой ситуацией, но я хотел бы добавить, что в неакадемической среде вы также должны искать замену API как можно скорее. В ситуациях, когда мы были заблокированы в плохом API, как правило, выбирая решение для решения по другим причинам, я работал над заменой своих функций со временем. Ваши клиенты не будут такими терпимыми, как ваш профессор, поскольку они фактически должны использовать ваше программное обеспечение (или нет!), А не просто оценивать его.

Есть, конечно, ситуации, когда использование клейкой ленты является адекватным выбором для решения проблемы. Когда это приводит к такому плохому поведению, как вы описали, однако, лучше не полагаться на него слишком долго и начать работать над реальным ремонтом.

Ответ 4

Лучшая задача - повторное внедрение рассматриваемого API. Однако, как вы говорите, это очень тяжелый вес и, вероятно, решение, выходящее за рамки.

следующая лучшая вещь должна была бы обернуть API, если это возможно. В принципе, если вы можете заранее определить, что именно происходит с наборами данных, которые вызывают отказ, вы можете отказаться от вызовов, чтобы гарантировать детерминизм. Не похоже, что это сработает и для вас, поскольку вы предполагаете, что повторение вызова с одним и тем же набором данных иногда прекращается, когда он имеет бесконечную петлю при предыдущем вызове.

Учитывая приведенные выше варианты, недоступны:
Я думаю, что ваше текущее решение потока - это лучший из плохих вариантов. Спиннинг процесса вызова метода кажется слишком тяжелым, чтобы быть приемлемым с точки зрения производительности, даже если это безопаснее, чем использование потоков. Thread.stop() очень опасен, но если вы религиозно запретите любую блокировку, вы можете с ней справиться.