2009-08-02 2 views
11

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

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

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

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

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

ответ

11

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

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

Ссылка: JSR-000121 Application Isolation API Specification - Final Release

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

+1

Я принял ваш ответ из-за интересной ссылки на API изоляции. Спасибо за это! –

5

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

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

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

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

+0

Спасибо за ваш ответ, я думаю, что попробую этот подход. –

1

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

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

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

+0

Я не совсем согласен с вами здесь. Одновременно будет выполняться не более одного подпроцесса. В рамках этого подпроцесса действительно будет проведено интенсивное вычисление с использованием ЦП, поэтому я не понимаю, почему создание другого процесса является таким большим делом. Я полагаю, вы предполагаете, что будет много подпроцессов, но моей программе всегда будет только один. Однако для передачи и извлечения данных на него и из него возникнут некоторые накладные расходы, но это было бы слишком сложно сделать. Хорошо, спасибо за ваш ответ. –

+0

Я забочусь о стоимости __starting__ процесса, а не числа или живых процессов в любой момент времени. Стоимость процесса >> стоимость потока с точки зрения времени запуска. Я вроде бы предполагаю, что вы делаете повторные обращения к этому API, что я считаю справедливым, учитывая вопрос, как написано (хотя, возможно, это не относится к вашей реальной ситуации). Насколько интенсивно работает процессор, API не имеет особого значения, так как вы платите эту стоимость независимо от исправления. –

2

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

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

+0

Ну, я видел (довольно дорогое) деловое программное обеспечение, которое часто разбивалось и все еще принималось всеми, поскольку это единственное доступное программное обеспечение для определенной цели. Обходной путь существовал также, как и в моем приложении: убить процесс и повторить попытку ;-) Я думаю, что Джоэл говорил о программном обеспечении, подобном этому в подкасте SO, но я не могу найти этот эпизод прямо сейчас. Я имею в виду действительно неприятное программное обеспечение, ненадежное и с ужасным пользовательским интерфейсом, но все еще чрезвычайно успешным, потому что это единственное решение действительно сложной проблемы. –

+2

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