Как изолировать вашу программу от обращений к «плохому» API?

StackOverflow https://stackoverflow.com/questions/1218790

Вопрос

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

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

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

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

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

Это было полезно?

Решение

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

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

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

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

Другие советы

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top