Как изолировать вашу программу от обращений к «плохому» API? - PullRequest
12 голосов
/ 02 августа 2009

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

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

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

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

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

Ответы [ 4 ]

11 голосов
/ 02 августа 2009

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

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

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

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

5 голосов
/ 02 августа 2009

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

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

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

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

2 голосов
/ 02 августа 2009

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

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

1 голос
/ 02 августа 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...